• cf1


    1.Codeforces Round #729 (Div. 2)  B. Plus and Multiply

     

    题解:枚举 a 的次方,若 n 减去 a 的次方是 b 的整倍数,则 n 满足要求,注意特判 a = 1 与 b = 1 。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
     
    ll T,n,a,b;
     
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
     
    int main(){
        cin>>T;
        while(T--){
            bool p=0;
            read(n),read(a),read(b);
            if(b==1){
                printf("Yes
    "); continue;
            }
            if(a==1){
                if((n-1)%b==0) printf("Yes
    ");
                else printf("No
    ");
                continue;
            }
            for(ll i=1;i<=n;i*=a){
                if((n-i)%b==0){
                    printf("Yes
    ");
                    p=1;break;
                }
            }
            if(!p){
                printf("No
    ");
            }
        }
        return 0;
    }
    View Code

    2.Codeforces Round #724 (Div. 2) C. Diluc and Kaeya

     

     大意:给定DK序列的所有前缀中,对于每个前缀可以分为k段,使得分为的k段长度相同,且每段中D与K数量之比相同,求对于每个前缀这个k的最大值。

     题解:将D出现的次数记为x,K出现的次数记为y,用(x,y)表示每个前缀,可得到坐标系中的n个点。其中,第 i 个点与原点相连穿过第 1~i 个点的数量就为答案。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<map>
    using namespace std;
    #define ll long long
     
    const int maxn=5e5+5; 
     
    int T,n;
    char a;
     
    int gcd(int a,int b){
        int c;
        while(a%b){
            c=a%b;
            a=b;
            b=c;
        }
        return b;
    }
     
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
     
    int main(){
        cin>>T;
        while(T--){
            map<pair<int,int>,int > mp;
            int sum1=0,sum2=0;
            cin>>n;
            for(int i=1;i<=n;i++){
                cin>>a;
                if(a=='D') sum1++;
                else sum2++;
                pair<int,int> c;
    //            cout<<sum1<<" "<<sum2<<endl;
                if(sum1==0){
                    c.first=0;c.second=0;
                }
                else if(sum2==0){
                    c.first=1;c.second=0;
                }
                else{
                    int g=gcd(sum1,sum2);
    //                cout<<g<<endl;
                    int x1=sum1/g,x2=sum2/g;
                    c.first=x1;c.second=x2;
                }
                mp[c]++;
                cout<<mp[c]<<" ";
            }
            cout<<endl;
        }
        
        return 0;
    }
    View Code

    3.Codeforces Round #645 (Div. 2) Celex Update

     

     大意:每次只能向下或者向右走,问两点间经过数字之和不同的路径有多少条?

     题解:起点为(x1,y1),终点为(x2,y2),则答案为(x2-x1)*(y2-y1)+1 。

    4.Codeforces Round #645 (Div. 2)  D. The Best Vacation

     

     大意:一年有n个月,第 i 个月有 d[i] 天,而每个月的第 k 天可以获得 k 点拥抱。你要旅游连续 x 天,问可以获得拥抱的最大值为多少?

     题解:贪心可以发现,获得最大值时,旅游总是在某个月的最后一天结束。枚举每个月,假定这个月的最后一天结束,向前二分找到开始的月份,统计答案,取max。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
     
    const int maxn=4e5+50;
     
    ll n,x,d[maxn];
    ll Sum[maxn],tot[maxn];
     
    int find(int k,int l,int r){
        if(l==r) return l;
        int m=l+r>>1;
        if(Sum[k]-Sum[m]<x) return find(k,l,m);
        return find(k,m+1,r);
    }
     
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
     
    int main(){
        cin>>n>>x;
        ll sum=0,Max=0;
        for(int i=1;i<=n;i++){
            read(d[i]); d[i+n]=d[i];
        }
        for(int i=1;i<=2*n;i++){
            Sum[i]=Sum[i-1]+d[i];
            tot[i]=tot[i-1]+(d[i]+1)*d[i]/2;
        } 
        for(int i=1;i<=2*n;i++){
            if(Sum[i]<x) continue;
            int y=find(i,1,i);
            ll num=x-Sum[i]+Sum[y];
            Max=max(Max,tot[i]-tot[y]+(d[y]*2+1-num)*num/2);
        }
        cout<<Max<<endl;
        return 0;
    }
    View Code

    5.Codeforces Round #722 (Div. 2) C. Parsa's Humongous Tree

     

     大意:一棵树的每个节点有两个值 l [ i ] 和 r [ i ] ,这个节点的权值为 a[ i ],a要满足 l [i] <= a [i] <= r [i] ,一条路径的值为路径两点的权值之差的绝对值,求所有路径的值之和的最大值。

     题解:dp[ i ][ 0 ] 和 dp[ i ][ 1 ] 分别表示  i  节点取左、右值时其子树路径之和的最大值,设 v 是 i 的子节点,则有

                dp[ i ][ 0 ]  += max( dp[ v ][ 0 ] + abs( l[ i ] - l[ v ] ) , dp[ v ][ 1 ] + abs( l[ i ] - r[ v ] ) )

                dp[ i ][ 1 ]  += max( dp[ v ][ 0 ] + abs( r[ i ] - l[ v ] ) , dp[ v ][ 1 ] + abs( r[ i ] - r[ v ] ) )

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long 
    
    const int maxn=2e5+50;
    const int maxm=4e5+50;
    
    int T,n,l[maxn],r[maxn];
    int fir[maxn],nex[maxm],to[maxm],ecnt; 
    ll dp[maxn][2];
    
    void add(int u,int v){
        nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;
    } 
    
    void dfs(int x,int f){
        dp[x][0]=dp[x][1]=0;
        for(int e=fir[x];e;e=nex[e]){
            int v=to[e];
            if(v==f) continue;
            dfs(v,x);
            dp[x][0]+=max(dp[v][0]+abs(l[x]-l[v]),dp[v][1]+abs(l[x]-r[v]));
            dp[x][1]+=max(dp[v][0]+abs(r[x]-l[v]),dp[v][1]+abs(r[x]-r[v]));
        }
    }
    
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
    
    int main(){
        cin>>T;
        while(T--){
            memset(fir,0,sizeof(fir));
            memset(nex,0,sizeof(nex));
            memset(to,0,sizeof(to)); ecnt=0;
            cin>>n;
            for(int i=1;i<=n;i++){
                read(l[i]),read(r[i]); 
            }
            int x,y;
            for(int i=1;i<n;i++){
                read(x),read(y);
                add(x,y);add(y,x) ;
            }
            dfs(1,0);
            cout<<max(dp[1][0],dp[1][1])<<endl;
        }
        return 0;
    }
    View Code

    6.Codeforces Round #264 (Div. 2) D. Gargari and Permutations

     大意:求 k 个 n 的全排列的最长公共子序列

     题解:(1)可以将 k 个序列中均满足 i 出现在 j 的前面的 i 与 j 连边,求最长路

                  (2)   设dp[ i ] 为在第一个序列中到 i 能与所有序列形成的最长公共子序列长度,则往 i 后面枚举 j ,如果 a[ j ] 在其他序列中出现的位置均在 a[ i ] 后面,则 dp[ j ] = max( dp[ j ] , dp[ i ] +1 )。

                          最后将 dp[ i ] 取 max

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    
    const int maxn=1000+50;
    const int maxm=1e6+5;
    
    int n,k,a[6][maxn],id[6][maxn],dp[maxn]; 
    
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
    
    int main(){
        cin>>n>>k;
        for(int i=1;i<=k;i++){
            for(int j=1;j<=n;j++){
                read(a[i][j]);
                id[i][a[i][j]]=j;
            }
        }
        for(int i=1;i<=n;i++) dp[i]=1;
        for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++){
            bool p=0;
            for(int t=2;t<=k;t++){
                if(id[t][a[1][j]]<=id[t][a[1][i]]){
                    p=1;break;
                }
            }
            if(p) continue;
            dp[j]=max(dp[j],dp[i]+1);
        }
        int ans=0;
        for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
        cout<<ans;
        return 0;
    }
    View Code

    7.Codeforces Round #486 (Div. 3) D. Points and Powers of Two

     大意:给定n个数,找出最多的数,使他们任意两个数之差的绝对值为二的整次幂

     题解:可以证明,最多只能找出3个数。枚举大小为中间的数为a,枚举2的次幂 k,查找 a-k 与 a+k 是否存在,存在则答案为3。若不存在继续判断答案为 2 的情况即可。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    
    const int maxn=2e5+50;
    
    ll n,a[maxn],br,t=1,ans;
    ll er[100];
    
    bool find(ll x,int l,int r){
        if(l==r){
            if(a[l]!=x) return false;
            return true;
        }
        int m=l+r>>1;
        if(a[m]<x) return find(x,m+1,r);
        if(a[m]>x) return find(x,l,m);
        if(a[m]==x) return true;
    }
    
    bool pd(int x){
        for(int i=0;i<=t;i++)
        if(x%er[i]==0) return true;
        return false;
    }
    
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
    
    int main(){
        cin>>n;
        er[0]=1;
        for(int i=1;;t++,i++){
            er[i]=er[i-1]*2;
            if(er[i]>2e9) break; 
        } 
        for(int i=1;i<=n;i++) read(a[i]);
        sort(a+1,a+1+n);
        if(n==1){
            ans=1;
            cout<<ans<<endl<<a[1]; return 0;
        }
        if(n==2){
            if(pd(a[2]-a[1])){
                ans=2;
                cout<<ans<<endl<<a[1]<<" "<<a[2]; return 0;
            }
            else{
                ans=1;
                cout<<ans<<endl<<a[1]<<" ";return 0;
            }
        }
        for(int i=2;i<n;i++){
            for(int j=0;j<=t;j++){
                ll x=a[i]-er[j],y=a[i]+er[j];
                if(find(x,1,i-1)&&find(y,i+1,n)){
                    ans=3;
                    cout<<ans<<endl<<x<<" "<<a[i]<<" "<<y;return 0;
                }
            }
        }
        for(int i=1;i<n;i++){
            for(int j=1;j<=t;j++){
                ll x=a[i]+er[j];
                if(find(x,i+1,n)){
                    ans=2;
                    cout<<ans<<endl<<a[i]<<" "<<x; return 0;
                }
            }
        }
        ans=1;
        cout<<ans<<endl<<a[1];
        return 0;
    }
    View Code

    8.Codeforces Round #731 (Div. 3) E. Air Conditioners

     

     大意:有n个点,k个空调,给出每个空调的位置a[ i ]和温度 t[ i ],对于一个点 i ,它的温度为,求每个点的温度

     题解:设L[ i ] 表示点 i 以及 i 左边的点对 i 的贡献,即 i 点有空调时 L[ i ] = min ( L[ i-1 ] +1 , t[ i ] ) , 否则 L [ i ] = L[ i-1 ] + 1

    同样,设R[ i ] 表示点 i 以及 i 右边的点对 i 的贡献,即 i 点有空调时 R[ i ] = min ( R[ i+1 ] +1, t[ i ] ), 否则 R [ i ] = R[ i+1 ] + 1

    最后 i 点的答案就为 min( L[ i ] , R[ i ] )

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    
    const int maxn=3e5+50;
    const int maxx=2e9;
    
    ll L[maxn],R[maxn],T[maxn];
    int TT,n,k;
    bool P[maxn];
    
    struct node{
        int p; ll t;
    }a[maxn];
    
    int cmp(const node &a,const node &b){
        return a.p<b.p;
    }
    
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
    
    int main(){
        cin>>TT;
        while(TT--){
            cin>>n>>k;
            memset(P,0,sizeof(P));
            for(int i=1;i<=k;i++){
                read(a[i].p);
                P[a[i].p]=true;
            } 
            for(int i=1;i<=k;i++) read(a[i].t);
            for(int i=1;i<=k;i++) T[a[i].p]=a[i].t;
            for(int i=0;i<=n+1;i++) L[i]=maxx,R[i]=maxx;
            sort(a+1,a+1+k,cmp);
            for(int i=a[1].p;i<=n;i++){
                if(P[i]) L[i]=min(L[i-1]+1,T[i]);
                else L[i]=L[i-1]+1;
            }
            for(int i=a[k].p;i>=1;i--){
                if(P[i]) R[i]=min(R[i+1]+1,T[i]);
                else R[i]=R[i+1]+1;
            }
            for(int i=1;i<=n;i++) cout<<min(L[i],R[i])<<" ";
            cout<<endl;
        }
        return 0;
    }
    View Code

    9.Codeforces Round #732 (Div. 2) B. AquaMoon and Stolen String

     

     

     

     大意:有奇数n个字符串,将其中n-1个两两配对,一对字符串中相同位置可以交换,如aaaa与bbbb可以交换为aabb与bbaa,给出这n-1个交换后的串,求剩下的那一个串

     题解:注意 a^b^b = a , 对于输入的 2*n-1 个串,对他们的位置 i 进行异或,得到的答案就是剩下的那个串的位置 i 。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    
    const int maxn=2e5+50;
    
    int T,n,m;
    string a[maxn];
    
    int main(){
        cin>>T;
        while(T--){
            cin>>n>>m;
            for(int i=1;i<=2*n-1;i++) cin>>a[i];
            for(int i=0;i<m;i++){
                int cur=0;
                for(int j=1;j<=2*n-1;j++) 
                cur^=(a[j][i]-'a');
                cout<<char(cur+'a');
            }
            cout<<endl;
        }
        return 0;
    }
    View Code

    10.Codeforces Round #732 (Div. 2)C. AquaMoon and Strange Sort

     

     大意:有n个数,他们的方向开始都朝右,每次操作可以将一个数与它相邻的数交换,同时这两个数的方向改变,问能不能使得这n个数不降排列且每个数的方向都向右?

     题解:方向不变,则每个数都要交换偶数次。记录原数列中每个数出现的奇数位置、偶数位置的次数,再将数列排序,若排序后的数列中每个数出现在奇数、偶数位置的次数与原数列不同,则不满足;否则满足。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    
    const int maxn=1e5+50;
    
    int T,n,a[maxn],odd[maxn],even[maxn];
    
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
    
    int main(){
        cin>>T;
        while(T--){
            memset(odd,0,sizeof(odd));
            memset(even,0,sizeof(even));
            cin>>n;
            for(int i=1;i<=n;i++){
                read(a[i]);
                if(i%2) odd[a[i]]++;
                else even[a[i]]++;
            }
            sort(a+1,a+1+n);
            for(int i=1;i<=n;i++){
                if(i%2) odd[a[i]]--;
                else even[a[i]]--;
            }
            bool p=0;
            for(int i=1;i<=1e5;i++){
                if(even[i]!=0||odd[i]!=0){
                    p=1;break;
                }
            }
            if(p){
                cout<<"NO"<<endl;
            }
            else cout<<"YES"<<endl;
        }
        return 0;
    }
    View Code

    11.The 2020 ICPC Asia Macau Regional Contest F. Fixing Networks

     

     大意:有n个点,要求每个点恰好与d个点相连,且这n个点分为c块,块内各点连通,块与块之间不连通,能否构造?

     题解:每个点需要连接d个点,则一块至少需要d+1个点,即( d+1 )*c 需要小于等于n,同时,n和d不能都为奇数。单独判断d=0和d=1,对于其他情况,取d+1个点为一个块,这个块内的点两两相连,可以构造

    c-1个这样的块。对于剩下的m个点,它们需要构成一块,取 k=d/2 (向下取整),这m个点每个点向其前后k个点分别连边,若d为奇数,此时m必然为偶数,则再将每个点与其对称点连边即可。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
     
    ll n,d,c,ans[100000+50],t;
     
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
     
    int main(){
        cin>>n>>d>>c;
        if((d+1)*c>n||(n%2&&d%2)){
            cout<<"No"<<endl; return 0;
        }
        if(d==0){
            if(n==c){
                cout<<"Yes"<<endl;
            }
            else{
                cout<<"No"<<endl;
            }
            return 0;
        }
        if(d==1){
            if(n==2*c){
                cout<<"Yes"<<endl;
                for(int i=1;i<=n;i++){
                    if(i%2) cout<<i+1<<endl;
                    else cout<<i-1<<endl;
                }
            }
            else{
                cout<<"No"<<endl;
            }
            return 0;
        }
        cout<<"Yes"<<endl;
        for(int i=1;i<=(c-1)*(d+1);i++){
            ll id=(i-1)/(d+1),st=id*(d+1)+1,ed=(id+1)*(d+1);
            for(int j=st;j<=ed;j++){
                if(j==i) continue;
                cout<<j<<" ";
            }
            cout<<endl;
        }
        ll k=d/2,sum=n-(c-1)*(d+1),st=(c-1)*(d+1)+1;
        for(int i=st;i<=n;i++){
            t=0;
            for(int j=i+1;j<=i+k;j++){
                if(j>n) ans[++t]=j-sum;
                else if(j<st) ans[++t]=j+sum;
                else ans[++t]=j;
            }
            if(d%2){
                int x=i+sum/2; if(x>n) x-=sum;
                ans[++t]=x;
            }
            for(int j=i-k;j<=i-1;j++){
                if(j>n) ans[++t]=j-sum;
                else if(j<st) ans[++t]=j+sum;
                else ans[++t]=j;
            }
            sort(ans+1,ans+1+t);
            for(int i=1;i<=t;i++) cout<<ans[i]<<" ";
            cout<<endl;
        }
        return 0;
    }
     
    View Code

    12.The 2020 ICPC Asia Macau Regional Contest G. Game on Sequence

     

     大意:有一个长度为n的序列,Grammy和Alice在这个序列上玩一个游戏,他们从位置k开始,Grammy先进行,每次他们需要从当前数向后跳,且要满足跳到的数与当前数在二进制表示上最多一位不同,最后不能跳的人输掉游戏。现在有m个操作,操作 1 k 表示在这个序列的最后面加上一个数 k ,操作 2 k 表示游戏从位置 k 开始,输出谁能赢下这个游戏。

     题解:对于两个位置 i,j ( i<j ) 并且 a[ i ] = a[ j ] ,若 a[ j ]必败,由于a[ i ]可以跳到 a[ j ],则a[ i ]必胜;若a[ j ] 必胜,表示a[ j ]可以跳到后面一个必败的点,则a[ i ]同样可以跳到那个点,a[ i ]必胜。可以看出,如果一个数后面有与它相同的数,则这个数必胜。所以只需要判断一个数最后出现的位置能不能必胜。从后向前推,若当前数可以跳到的数中,有必败的数,则当前数必胜,否则当前数必败。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    const int maxn=4e5+50;
    
    int n,m,a[maxn],loc[maxn];
    bool f[maxn];
    
    int cmp(int x,int y){
        return loc[x]>loc[y];
    }
    
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
    
    void work(){
        int lim=256;
        memset(f,1,sizeof(f));
        vector<int> v;
        for(int i=0;i<lim;i++){
            if(loc[i]) v.push_back(i);
        }
        sort(v.begin(),v.end(),cmp);
        for(int i=0;i<v.size();i++){
            bool p=0;
            int x=v[i];
            for(int k=0;k<8;k++)
            if(!f[x^(1<<k)]) p=1;
            if(p) f[x]=1;
            else f[x]=0;
        }
    }
    
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            read(a[i]);
            loc[a[i]]=i;
        }
        work();
        int op,k;
        while(m--){
            cin>>op>>k;
            if(op==1){
                a[++n]=k;
                loc[k]=n;
                work();
            }
            else{
                if(loc[a[k]]==k){
                    if(f[a[k]]) cout<<"Grammy"<<endl;
                    else cout<<"Alice"<<endl;
                }
                else cout<<"Grammy"<<endl;
            }
        }
        return 0;
    }
    View Code

    13.Codeforces Round #721 (Div. 2) C. Sequence Pair Weight

     

     大意:一个序列中,一对相同元素可以提供一重量,给定一个n个数的序列,求这个序列的所以子串 ( 包括自己且要求连续 )的重量的和。

     题解:设dp[ i ]为以第 i 位结束的所有串的重量和,则答案为dp[ 1 ] + dp[ 2 ] +...+ dp[ n ]。对于第 i 位,如果在第 j 位 ( j < i )的数a[ j ] = a[ i ],则它的贡献为 j ,所以 dp[ i ] = dp[ i-1 ] + ∑ j ( j < i,且a[ j ] = a[ i ] )

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    const int maxn=1e5+50;
    
    ll T,n,a[maxn];
    ll dp[maxn];
    
    map<ll,ll> mp;
    
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
    
    int main(){
        cin>>T;
        while(T--){
            mp.clear();
            read(n);dp[0]=0; ll ans=0;
            for(int i=1;i<=n;i++){
                read(a[i]);
                mp[a[i-1]]+=i-1;
                dp[i]=dp[i-1]+mp[a[i]];
                ans+=dp[i];
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code

    14.Codeforces Round #683 (Div. 2, by Meet IT) D. Catching Cheaters

     

     

     大意:给你两个字符串A和B,C和D分别为A和B的子串,定义S(C,D) = 4*LCS(C,D) - |C| - |D| ,其中 LCS(C,D) 表示C和D的最长公共子序列,对于A和B的任意子串C和D,求出S(C,D) 的最大值。

     题解:设dp[ i ][ j ] 为以a[ i ] 结尾,b[ j ]结尾的两个串的最大S值,枚举 i,j,如果a[ i ] = b[ j ],则 LCS增加1,S值增加2,有dp[ i ][ j ]=max( dp[ i ][ j ], dp[ i-1 ][ j-1 ] + 2 );如果 a[ i ] ≠ b[ j ],则 dp[ i ][ j ] = max( dp[ i ][ j ],dp[ i ][ j-1 ] -1 ) ,dp[ i ][ j ] = max( dp[ i ][ j ],dp[ i-1 ][ j ] -1 )。最后对每个dp[ i ][ j ] 取max得到答案。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
     
    const int maxn=5050;
     
    int n,m,dp[maxn][maxn],ans;
    char a[maxn],b[maxn]; 
     
    template<typename T>void inline read(T &aa){
        ll ff=1;char cc=getchar();aa=0;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
        aa*=ff;
    }
     
    int main(){
        cin>>n>>m;
        cin>>a+1;
        cin>>b+1;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+2;
            else{
                dp[i][j]=max(dp[i][j],dp[i-1][j]-1);
                dp[i][j]=max(dp[i][j],dp[i][j-1]-1);
            }
            ans=max(ans,dp[i][j]);
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

    15.The 15th Heilongjiang Provincial Collegiate Programming Contest C. Cornelia Street

     大意:一个字符串S由 AA....ABBB...BAA..Aa 组成,其中A与B的长度相同,但数量不一定相同,a是A的一个前缀,求最短的A,B。

     题解:先求出整个串的hash值,枚举所求长度,算出每段的hash值,若除开A的前缀a之外只有两种hash值,则满足要求。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    
    const int maxn=8e5+50;
    const ll base=131;
    const ll mod=1e9+7;
    
    char a[maxn];
    ll hhash[maxn],ans,mul[maxn];
    
    int main(){
        cin>>a+1;
        int len=strlen(a+1);mul[0]=1;
        for(int i=1;i<=len;i++) hhash[i]=(hhash[i-1]*base+(ll)a[i])%mod,mul[i]=mul[i-1]*base%mod;
        int id;
        for(int l=1;l<=len/2;l++){
            int tot=0;ll sum=0,pre; bool p=0;
            for(int i=l;i<=len;i+=l){
                ll pp=hhash[i]-mul[l]*hhash[i-l]%mod;
                if(pp<0) pp+=mod;
                if(sum!=pp){
                    if(sum==0) pre=pp;
                    if(tot==1) id=i-l+1;
                    sum=pp; tot++;
                    if(tot>=3){
                        if(tot==3&&sum==pre) continue;
                        p=1;break;
                    }
                }
            }
            if(p) continue;
            int las=len%l;
            if((hhash[len]-mul[las]*hhash[len-las]%mod+mod)%mod==hhash[las]){
                ans=l; break;
            }
        }
    //    cout<<ans<<endl;
        for(int i=1;i<=ans;i++) cout<<a[i]; cout<<" ";
        for(int i=id;i<=id+ans-1;i++) cout<<a[i];
        return 0;
    }
    View Code

    2021.7.16

  • 相关阅读:
    AJAX教程
    HTTP请求响应对照表
    JQuery教程
    服务器网络编程一
    servlet
    DOM浏览器文档模型
    在centos7下安装nodejs14
    将C#控制台程序部署到Linux系统
    在gitlab上通过python服务钩子实现自动部署
    Centos 7搭建Gitlab服务器超详细
  • 原文地址:https://www.cnblogs.com/rlddd/p/14989080.html
Copyright © 2020-2023  润新知