其他分享
首页 > 其他分享> > Codeforces Round #717 (Div. 2) A-C题解

Codeforces Round #717 (Div. 2) A-C题解

作者:互联网

心得:打这个比赛的时候由于读题,自己变成一个大傻逼了,反思了一晚上 ,确实还是自己做的不够好,下面我口胡一篇自己的对于这几个题的解答。

比赛地址传送门

开始了:
A

题意:给出长度为N 的数组和可以操作的最大次数,然后要求你找出
非负的最小的数组字典序,然后有一个操作,选择一个数组+1,一个数组-1,直到找到最小字典序,或者操作做完。

题解:直接就是把所有的数字[1–n-1]这个范围的数字依次减 然后+到第N个数上,特别要小心一下中间的的过程可能初始就是为0

int ans[maxx];
int main(){
    int t;cin>>t;
    while(t--){
      int n,k;cin>>n>>k;
      mse(ans,-1);
      for(int i=1;i<=n;i++) cin>>ans[i];
      int pos=1;
      for(int i=k;i>=1;i--){
        if(ans[pos]>0) ans[pos]--,ans[n]++;
         else {
            while(ans[pos]==0) pos++;
            if(pos>=n) break;
            ans[pos]--,ans[n]++;
         }
      }
      for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
      cout<<endl;
    }
    return 0;
}

B

题意:给你N个数字,然后要求每次删除两个数增加在这个位置一个数字(这个数字是删除的两数的异或和),最终问你能不能找到长度大于等于2并且这个数组的所有数字相等
题解:既然要使这个数组全部相等,不能简单的定义为判断所有数异或==0,就可以找到了 ,这只是一种情况,譬如[3,3,3,0]这种情况也是满足的,那么换一个思维来看,是不是可以简单 的找一下前缀异或和,如果该数组可以满足题意,那么是不是最后一位数字起到了最关键的作用,找出前缀和=sum,若前面有相等的那么必然中间过程可以异或等于0,那么我们就可以直接判断最后sum的值,和前面所有异或为0的区间,能不能找到一个前缀和为sum的,若可以找到那么这个[1-N]某些局部区间异或值一定可以变成[sum,sum,sum]

 
int ans[maxx];
int main(){
    int t;cin>>t;
    while(t--){
      int n;cin>>n;
      int flag=0,pos=0;
      for(int i=1;i<=n;i++) cin>>ans[i];
      for(int i=2;i<=n;i++){
        ans[i]^=ans[i-1];
         if(ans[i]==0) pos=i;
      }
      int a=ans[n];
      for(int i=1;i<=pos;i++) if(ans[i]==ans[n]) flag=1;
      if(flag) cout<<"YES"<<endl;
      else cout<<"NO"<<endl;
    }
    return 0;
}

C

题意:给你N个数字,然后问你是否现在这个数组分成2个集合 , 能够找到一种情况 可以使这两个集合总和一样,如果可以,那么删除一个最小的数,使得不满足这个情况。
题解:首先,我们可以得出一个结论,两个集合要想相等,那么必然这个数组总和是偶数,如果为奇数那就直接可以不用操作,那么我们来看如果为偶数的情况,我们可以使整个数组同时>>1.前提是所有的数组都可以除,那么是不是一定可以变成最简单数,这个操作对于答案没任何影响,比如【2,6,8,12】–> 【1,3,4,6】,最终可以分成2个为7的,那么这样使得数组最简化,然后我们可以判断一下,如果这个数组中,某个数>sum(总和)/2,这种情况也是不需要处理的,比如[1,1,1,1,12],接下来的这个就是关键了,这个真的是我没有想到的找法,我们现在不确定是否可以在这个序列中任意构成一个集合总和=sum/2,那么就要找一个完美的处理方法,我们可以使用01背包原理,来找,这样子就可以找出一种可以构成sum/2的总和值是否存在的情况,最后判断是否找到,找不到就可以不处理,否则就要处理一次

int dp[maxx];
int ans[maxx];
int main(){

   int n;cin>>n;
   int sum=0;
   for(int i=1;i<=n;i++) cin>>ans[i];
         int c=0,k=mod;
         for(int i=1;i<=n;i++){ c=0;
         int a=ans[i];
           while(a%2==0){
            a>>=1;c++;}
           k=min(c,k);
        }
       int flag=0;
         for(int i=1;i<=n;i++) {ans[i]=ans[i]>>k;sum+=ans[i];}
       if(sum&1) cout<<0<<endl;
       else{
           flag=0;
        for(int i=1;i<=n;i++) if(ans[i]>sum/2) {flag=1;break;}
        if(flag) cout<<0<<endl;
       else{
            int mn=mod,pos,vis=0; flag=0;
        for(int i=1;i<=n;i++){
                if(ans[i]==sum/2) vis=1;
            if(mn>ans[i]&&ans[i]%2==1){mn=ans[i]; pos=i;}
        }
        if(vis) {
               mn=mod; flag=1;
             for(int i=1;i<=n;i++) if(mn>ans[i]){mn=ans[i]; pos=i;}
        }
        else{
            for(int i=1;i<=n;i++)
            {
                for(int j=sum/2;j>=ans[i];j--) dp[j]=max(dp[j],dp[j-ans[i]]+ans[i]);
            }
            if(dp[sum/2]==sum/2) flag=1;
        }
        if(flag) cout<<1<<endl<<pos<<endl;
        else cout<<0<<endl;
        }
       }


    return 0;
}

标签:717,题解,sum,pos,int,flag,数组,ans,Div
来源: https://blog.csdn.net/weixin_45187630/article/details/116021039