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