Problem A 小花梨的字符串

https://acm.ecnu.edu.cn/contest/173/problem/A/

题意:对区间子字符串排列,使得满足条件,求排列最长。

题解:

C++版本一

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
#define endl "\n"
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=100000+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m,k,p,l,r,u,v;
int ans,cnt,flag,temp,sum;
int a[N];
char str[N];
struct node{};
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);
    //scanf("%d",&t);
    //while(t--){
    scanf("%d%d",&n,&m);
    cin>>str;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&l,&r);
        cout<<(r-l+1)*(r-l+2)/2<<endl;
    }
    //}

#ifdef DEBUG
	printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Hello world!" << endl;
    return 0;
}

Problem B 小花梨的三角形

https://acm.ecnu.edu.cn/contest/173/problem/B/

题意:统计三个顶点不完全相同的三角形个数。

题解:枚举

C++版本一

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
#define endl "\n"
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=100+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m,k,p,l,r,u,v;
int ans,cnt,flag,temp,sum;
bool vis[N][N][N];
char str[N][N];
struct node{};
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);
    //scanf("%d",&t);
    //while(t--){
    scanf("%d",&n);
    for(int i=1;i<=n+1;i++)
        scanf("%s",str[i]+1);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=i;j++){
            for(int k=i+1;k<=n+1;k++){
                int a[4];
                a[0]=str[k][j]-'a';
                a[1]=str[i][j]-'a';
                a[2]=str[k][j+k-i]-'a';
                sort(a,a+3);
                //cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
                vis[a[0]][a[1]][a[2]]=1;
            }

        }
    }
    for(int i=2;i<=n;i++){
        for(int j=1;j<i;j++){
            for(int k=j+1;k<=i&&i+k-j<=n+1;k++){
                int a[4];
                a[0]=str[i][j]-'a';
                a[1]=str[i][k]-'a';
                a[2]=str[i+k-j][k]-'a';
                sort(a,a+3);
                //cout<<i<<" "<<j<<" "<<k<<" "<<i+k-j<<endl;
                //cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
                vis[a[0]][a[1]][a[2]]=1;
            }

        }
    }
    for(int i=0;i<26;i++){
        for(int j=i;j<26;j++){
            for(int k=j;k<26;k++){
                ans+=vis[i][j][k];
            }
        }
    }
    cout<<ans<<endl;
    //}

#ifdef DEBUG
	printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Hello world!" << endl;
    return 0;
}

Problem C 小花梨判连通

https://acm.ecnu.edu.cn/contest/173/problem/C/

题意:有K张联通图,求使得 𝑖和𝑗在这 𝑘张图中都是连通的j的个数

C++版本一

题解:直接 dfs 、BFS 或者并查集对每张图进行连通块染色, 或者并查集对每张图进行连通块染色,  两个点在 k张图中都相邻说明这两个点在 张图中都相邻说明这两个点在 张图中都相邻说明这两个点在 k张图的染色 都是一样的 
map<vector<int>,int>存下每个点在 k张图的颜色序  列出现的次数即可 

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
#define endl "\n"
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=200000+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m,k,p,l,r,u,v;
int ans,cnt,flag,temp,sum;
int pre[20][N];
char str;
bool vis[N];
struct node{};
vector<int>G[N];
vector<int>V[N];
map<vector<int>,int>mp;
int find(int *pre,int x){return pre[x]==x?x:pre[x]=find(pre,pre[x]);}
void dfs(int u){
    vis[u]=1;
    V[u].push_back(cnt);
    //cout<<u<<" "<<cnt<<endl;
    for(int i=0,j=G[u].size();i<j;i++){
        int v=G[u][i];
        if(!vis[v]){
            dfs(v);
        }
    }
}
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);
    //scanf("%d",&t);
    //while(t--){
    scanf("%d%d",&n,&m);
    for(int i=0;i<=m;i++)
        for(int j=1;j<=n;j++)
            pre[i][j]=j;
    for(int i=1;i<=m;i++){
        scanf("%d",&k);
        memset(vis,0,sizeof(vis));
        for(int j=1;j<=n;j++)
            G[j].clear();
        cnt=0;
        for(int j=1;j<=k;j++){
            scanf("%d%d",&u,&v);
            int fx=find(pre[i],u);
            int fy=find(pre[i],v);
            if(fx!=fy){
                pre[i][fy]=fx;
                G[u].push_back(v);
                G[v].push_back(u);
            }
        }
        for(int j=1;j<=n;j++){
            if(vis[j]==0)++cnt,dfs(j);
        }
    }
    for(int i=1;i<=n;i++){
        mp[V[i]]++;
    }
    for(int i=1;i<=n;i++)cout<<mp[V[i]]<<endl;
    //}

#ifdef DEBUG
	printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Hello world!" << endl;
    return 0;
}

C++版本二

 题解:对每一个图dfs求联通块并染色,处于同一个联通块中的点染成相同的颜色。染色之后对于图中的每一个点就有一个长度为k的颜色序列,两点在k张图中均联通即两个点的颜色序列完全相同。求每个点的颜色序列的hash值,并记录每种hash值出现了多少次。输出答案时将该点对应的hash值出现的次数输出即可。

#include "bits/stdc++.h"

using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 100;
const int inf = 0x3f3f3f3f;
bool vis[maxn];
vector<int> e[11][maxn];
unsigned long long ans[maxn];
int c[11][maxn];
int col = 0;
map<unsigned long long, int> mp;

void dfs(int deep, int now) {
    if (vis[now]) return;
    c[deep][now] = col;
    vis[now] = true;
    for (auto p:e[deep][now]) {
        dfs(deep, p);
    }
}

int main() {
    //freopen("in.txt", "r", stdin);
    int n, k, m;
    scanf("%d %d", &n, &k);
    int u, v;
    for (int i = 0; i < k; i++) {
        cin >> m;
        for (int j = 0; j < m; j++) {
            scanf("%d %d", &u, &v);
            e[i][u].push_back(v);
            e[i][v].push_back(u);
        }
        col = 0;
        memset(vis, 0, sizeof(vis));
        for (int j = 1; j <= n; j++) {
            if (!vis[j]) col++;
            dfs(i, j);
        }
    }
    unsigned long long hash;
    for (int i = 1; i <= n; i++) {
        hash = 0;
        for (int j = 0; j < k; j++) {
            hash = hash * mod + c[j][i];
        }
        mp[hash]++;
        ans[i] = hash;
    }
    for (int i = 1; i <= n; i++) {
        cout << mp[ans[i]] << endl;
    }
    return 0;
}

Problem D 小花梨的取石子游戏

https://acm.ecnu.edu.cn/contest/173/problem/D/

题意:按规则取石子,求第i轮必胜的人

题解:博弈,谁先拿到非1的堆,谁就是赢家。因为足够聪明,所有人必然使得自己永远占先机。

C++版本一

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
#define endl "\n"
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=200000+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m,k,p,l,r,u,v;
int ans,cnt,flag,temp,sum;
int a[N],b[N];
char str;
struct node{};
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);
    //scanf("%d",&t);
    //while(t--){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        a[i+n]=a[i];
    }
    flag=2*n+1;
    for(int i=2*n;i>=1;i--){
        if(a[i]!=1)
            flag=i;
        b[i]=flag;
    }
    for(int i=1;i<=n;i++){
        cout<<((min(n-1,b[i]-i))%2==0?"First":"Second")<<endl;
    }


    //}

#ifdef DEBUG
	printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Hello world!" << endl;
    return 0;
}

Problem E 小花梨的数组

https://acm.ecnu.edu.cn/contest/173/problem/E/

题意:

题解:线段树+tag标记

C++版本一

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
#define endl "\n"
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=100000+10;
const int M=1000000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m,k,p,l,r,u,v;
int ans,cnt,flag,temp,sum;
int f[M],prime[M],pre[N];
ll tree[N<<2],tag[N<<2];
ll POW(ll a,ll b,ll c){
    ll res=1;
    ll base=a%c;
    while(b){
        if(b&1)res=(res*base)%c;
        base=(base*base)%c;
        b>>=1;
    }
    return res;
}

void init(){
    f[1]=1;
    prime[0]=prime[1]=1;
    for(int i=2;i<=1e6;i++){
        if(prime[i]==0){
            pre[++cnt]=i;
            f[i]=i;
        }
        for(int j=1;j<=cnt&&pre[j]*i<=1e6;j++){
            prime[i*pre[j]]=1;
            f[i*pre[j]]=pre[j];
            if(i%pre[j]==0){
                break;
            }
        }
    }
}
void pushup(int rt){
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void pushdowm(int rt){
    tag[rt<<1]+=tag[rt];
    tag[rt<<1|1]+=tag[rt];
    tag[rt]=0;
}
void build(int l,int r,int rt){
    if(l==r){
        scanf("%lld",&tree[rt]);
        tag[rt]=0;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    pushup(rt);

}
void updata1(int l,int r,int rt,int L,int R){
    if(tree[rt]==r-l+1)
        return;
    if(L<=l&&r<=R){
        tag[rt]++;
        return;
    }
    pushdowm(rt);
    int mid=(l+r)>>1;
    if(L<=mid)updata1(l,mid,rt<<1,L,R);
    if(R>mid)updata1(mid+1,r,rt<<1|1,L,R);
    pushup(rt);
}
void updata2(int l,int r,int rt,int L,int R){
    if(tree[rt]==r-l+1)
        return;
    if(L<=l&&r<=R&&tag[rt]){
        tag[rt]--;
        return;
    }
    if(l==r){
        tree[rt]=tree[rt]/f[tree[rt]]%MOD;
        return;
    }
    pushdowm(rt);
    int mid=(l+r)>>1;
    if(L<=mid)updata2(l,mid,rt<<1,L,R);
    if(R>mid)updata2(mid+1,r,rt<<1|1,L,R);
    pushup(rt);
}
ll query(int l,int r,int rt,int L){
    if(tree[rt]==r-l+1)
        return 1;
    if(l==r){
        return tree[rt]*POW(f[tree[rt]],tag[rt],MOD)%MOD;
    }
    pushdowm(rt);
    int mid=(l+r)>>1;
    if(L<=mid)return query(l,mid,rt<<1,L);
    else return query(mid+1,r,rt<<1|1,L);
}
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);
    init();
    while(~scanf("%d%d",&n,&m)){
        memset(tree,0,sizeof(tree));
        build(1,n,1);
        for(int i=1;i<=m;i++){
            scanf("%d",&k);
            if(k==1){
                scanf("%d%d",&l,&r);
                updata1(1,n,1,l,r);
            }else if(k==2){
                scanf("%d%d",&l,&r);
                updata2(1,n,1,l,r);
            }else{
                scanf("%d",&l);
                cout<<query(1,n,1,l)<<endl;
            }
        }
    }

#ifdef DEBUG
	printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Hello world!" << endl;
    return 0;
}

Problem F 小花梨的无向图

https://acm.ecnu.edu.cn/contest/173/problem/F/

题意:

题解:

C++版本一

 

Problem G 小花梨的函数

https://acm.ecnu.edu.cn/contest/173/problem/G/

题意:

题解:

C++版本一

 

Problem H 小花梨的矩阵

https://acm.ecnu.edu.cn/contest/173/problem/H/

题意:

题解:

C++版本一

 

Problem I 小花梨点外卖

https://acm.ecnu.edu.cn/contest/173/problem/I/

题意:有两种优惠,最多选择一种,使得付款最小

题解:模拟

C++版本一

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
#define endl "\n"
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=100000+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m,k,p,l,r,a,b,c,d;
ll ans,cnt,flag,temp,sum;
int v[N];
char str;
struct node{};
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);
    //scanf("%d",&t);
    //while(t--){
    scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
    for(int i=1;i<=n;i++){
        scanf("%d",&v[i]);
        sum+=v[i];
    }
    if(sum>=a&&sum>=c){
        ans=sum-max(b,d);
    }else if(sum>=a){
        ans=sum-b;
    }else if(sum>=c){
        ans=sum-d;
    }else{
        ans=sum;
    }
    cout<<ans<<endl;
    //}

#ifdef DEBUG
	printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Hello world!" << endl;
    return 0;
}