A:http://codeforces.com/contest/1363/problem/A
题意:
n个数,能否从中找到x个数,使得sum为奇数
解析:
比赛时被自己弄吐了,懒得一个一个分析,索性直接暴力枚举
这破代码。。。各位不要学我啊。。。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=1e3+10; int a[maxn]; int main() { int t; cin>>t; while(t--) { int n,x; cin>>n>>x; int j=0,o=0; for(int i=1;i<=n;i++) { int md; cin>>md; if(md%2) j++; else o++; } if(j==0) { cout<<"NO"<<endl; } else if(o==0) { if(x%2) cout<<"YES"<<endl; else cout<<"NO"<<endl; } else { if(x%2==0) { int ok=0,jj=1,oo=0; while(jj<=j) { if((x-jj)<=o&&jj%2!=0) { ok=1;break; } else { jj++; } } if(ok) cout<<"YES"<<endl; else cout<<"NO"<<endl; } else { if(j>=x) cout<<"YES"<<endl; else { int jj=1; int ok=0; while(jj<=j) { if(jj%2!=0&&(x-jj)<=o) { ok=1;break; } jj++; } if(ok) cout<<"YES"<<endl; else cout<<"NO"<<endl; } } } } }
正经解析:
其实不合法只有这三种情况:
1:奇数数为0
2:偶数数为0,x为偶数
3:x==n,sum%2==0
x<n&&j>0&&o>0是一定可以的,一定可以凑出奇数和来
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1e3+10; int a[maxn]; int main() { int t; cin>>t; while(t--) { int n,x; cin>>n>>x; int sum=0,j=0; for(int i=1;i<=n;i++) { int md; cin>>md; sum+=md; if(md%2) j++; } int o=n-j; if((x==n&&sum%2==0)||(j==0)||(o==0&&x%2==0)) cout<<"NO"<<endl; else cout<<"YES"<<endl; } }
B:http://codeforces.com/contest/1363/problem/B
题意:
给出的串,要把它变成不含010,101的串来(非连续子串),操作是反转0/1,求最小操作数
解析:
只有四种情况合法:
全0:000000....
全1:11111111...
先全1,后全0:111111....000000.....
先全0,后全1:00000.....111111......
数据很小,所以可以暴力枚举每一种情况:156ms
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=1e3+10; int a[maxn]; int main() { int t; cin>>t; while(t--) { string s; cin>>s; int len=s.length(); if(len==1||len==2) { cout<<"0"<<endl;continue; } int cnt=0; for(int i=1;i<len;i++) { if(s[i]!=s[i-1]) cnt++; } int cnt1=0,cnt0=0; for(int i=0;i<len;i++) { if(s[i]=='1') cnt1++; else cnt0++; } if(cnt==1||cnt==0||cnt1==0||cnt0==0) { cout<<"0"<<endl;continue; } int minn=min(cnt1,cnt0);//00110 for(int i=0;i<len;i++) { int sum=0; for(int j=i;j>=0;j--) { if(s[j]=='0') sum++; } for(int j=i+1;j<len;j++) { if(s[j]=='1') sum++; } // cout<<i<<sum<<endl; minn=min(minn,sum); } for(int i=0;i<len;i++) { int sum=0; for(int j=i;j>=0;j--) { if(s[j]=='1') sum++; } for(int j=i+1;j<len;j++) { if(s[j]=='0') sum++; } // cout<<i<<sum<<endl; minn=min(minn,sum); } cout<<minn<<endl; } }
赛后反思:
假如数据很大,就需要优化,对于第3,4情况,反转数实际上是某个位置之前的0数目+之后的1数目/之前的1数目+之后的0数目
所以这里可以用前缀和处理一下:46ms,可以说是快多了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1e3+10; int s1[maxn],s0[maxn]; int main() { int t; cin>>t; while(t--) { string s; cin>>s; memset(s1,0,sizeof(s1)); memset(s0,0,sizeof(s0)); int len=s.length(); if(len==1||len==2) cout<<"0"<<endl; else { if(s[0]=='0') s0[0]++; else s1[0]++; for(int i=1;i<len;i++) { s0[i]=s0[i-1]; s1[i]=s1[i-1]; if(s[i]=='0') s0[i]++; else s1[i]++; } int minn=min(s1[len-1],s0[len-1]); for(int i=0;i<len;i++) { minn=min(minn,s1[i]+s0[len-1]-s0[i]); minn=min(minn,s0[i]+s1[len-1]-s1[i]); } cout<<minn<<endl; } } }
C:http://codeforces.com/contest/1363/problem/C
题意:
n个结点,n-1条边,只能拿掉入度为0/1的点,谁先拿到x,谁赢。
解析:
当x入度为0/1的时候,直接先手胜
由于两个人都很聪明,每一步都要按最优来处理,所以谁都不想让对方赢,谁都不愿意先去靠近x,所以要把x点留到最后,即x入度==1的时候,这个时候,就确定了胜负了。
所以看一下,除了x之外的n-1个点的奇偶性,当然也可以看n-2的奇偶性,这个无所谓的。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1e3+10; int d[maxn]; int main() { int t; cin>>t; while(t--) { int n , x; memset(d,0,sizeof(d)); cin>>n>>x; for(int i=1;i<n;i++) { int l,r; cin>>l>>r; d[l]++; d[r]++; } if(d[x]==0||d[x]==1) cout<<"Ayush"<<endl; else if((n-1)%2==0) cout<<"Ashish"<<endl; else cout<<"Ayush"<<endl; } }