Codeforces Round #640 (Div. 4)全部七题
A. Sum of Round Numbers
把一个数拆成几个整十/百/千...的数的和。
#include <bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while(t--) { int i,num,ans=0; vector<int>v; cin>>num; int m=1; while(num>0) { if(num%10!=0) { ans++; v.push_back(num%10*m); } num/=10; m*=10; } cout<<ans<<endl; for(i=0;i<v.size();i++)cout<<v[i]<<' '; cout<<endl; } return 0; }
B. Same Parity Summands
把n拆成k个奇偶性相同的数。注意,只有奇数个奇数的和才能构成奇数,所以需要特判n为奇且k为奇的情况,其余的话优先用1或者2凑即可(根据情况还得判断一下n和k或者n和2k的关系)。
#include <bits/stdc++.h> using namespace std; int main() { int t; cin>>t; int n,k,i; while(t--) { cin>>n>>k; if(n&1) { //奇数个奇数 if(k&1&&n>=k) { cout<<"YES"<<endl; for(i=1;i<=k-1;i++)cout<<1<<' '; cout<<n-(k-1)<<endl; } else cout<<"NO"<<endl; } else { //奇数个偶数 偶数个偶数 偶数个奇数 if(n>=k&&( (n-k+1)%2==1 )) { cout<<"YES"<<endl; for(i=1;i<=k-1;i++)cout<<1<<' '; cout<<n-(k-1)<<endl; } else if(n>=2*k) { cout<<"YES"<<endl; for(i=1;i<=k-1;i++)cout<<2<<' '; cout<<n-(k-1)*2<<endl; } else cout<<"NO"<<endl; } } return 0; }
C. K-th Not Divisible by n
求出第k个不能被n整除的数。
注意到:把所有数分为1~n,n+1~2*n,2*n+1~3*n.....每组数里有n-1个不能被n整除的数(或者说这些数构成了模n的一个剩余类)。然后凑到第k个即可。注意特判一下。
#include <bits/stdc++.h> using namespace std; long long n,nn,k,temp; int main() { int t; cin>>t; while(t--) { cin>>n>>k; nn=n*(k/(n-1)); k%=(n-1); if(k!=0)cout<<nn+k<<endl; else cout<<nn-1<<endl; } return 0; }
D. Alice, Bob and Candies
模拟...没啥意思(做成C语言期末上机题蛮好
#include <bits/stdc++.h> using namespace std; int n,c[200005]; int main() { int t; cin>>t; while(t--) { cin>>n; int i; for(i=1;i<=n;i++) { scanf("%d",&c[i]); } i=1; int j=n,a=0,b=0,pa=0,pb=0; int go=0;//0 alice 1 bob int cnt=0; while(1) { if(i-1==j)break; cnt++; if(go==0) { pa=0; while(i-1!=j&&pa<=pb) { a+=c[i]; pa+=c[i]; i++; } go=1; } else { pb=0; while(i-1!=j&&pb<=pa) { pb+=c[j]; b+=c[j]; j--; } go=0; } if(i-1==j)break; } cout<<cnt<<' '<<a<<' '<<b<<endl; } return 0; }
E. Special Elements
大概是求序列里满足这样条件的元素的个数:能被表示为l~r连续区间的和。
数据范围8e3,果断求前缀和后O(n2)枚举区间,用一下桶排方便直接累加答案。然后过掉肯定没问题啊T了...(题目说卡时间
进行优化,注意到每个元素的范围是1~n,因此枚举区间时如果发现区间和即将全部大于n后直接退出循环。
不过貌似好多人不加这个优化也能过。。
#include <iostream> #include <cstdio> using namespace std; int n,a[8005],sum[8005]; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } int main() { int t; t=read(); while(t--) { n=read(); int i; int b[8005]={0}; sum[0]=0; for(i=1;i<=n;i++) { a[i]=read(); sum[i]=sum[i-1]+a[i]; b[a[i]]++; } int l,r,ans=0; for(l=1;l<=n-1;l++) { for(r=l+1;r<=n&&(sum[r]-sum[l-1]<=n);r++) { if(b[sum[r]-sum[l-1]]) { ans+=b[sum[r]-sum[l-1]]; b[sum[r]-sum[l-1]]=0; if(ans==n)goto label; } } } label:; printf("%d\n",ans); } return 0; }
F. Binary String Reconstruction
构造一个含有指定"00"对,"01"对,"11"对个数的字符串。
构造。先构造11再构造00最后10,这样能让影响尽可能小。注意到题目说输入保证解总存在,所以不用担心只有00和11的情况。
注意根据交界处的情况进行处理。
#include <bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while(t--) { int n0,n1,n2,i; cin>>n0>>n1>>n2; if(n2) { for(i=1;i<=n2+1;i++)cout<<1; } if(n0) { for(i=1;i<=n0+1;i++)cout<<0; } if(n1) { if(n0&&n2)//从1开始输出 { for(i=1;i<=n1-1;i++)//之前11和00交界处已经有一个了 { if(i&1)cout<<1; else cout<<0; } } else if(n0) { for(i=1;i<=n1;i++) { if(i&1)cout<<1; else cout<<0; } } else if(n2)//必须从0开始 { for(i=1;i<=n1;i++) { if(i&1)cout<<0; else cout<<1; } } else { for(i=1;i<=n1+1;i++) { if(i&1)cout<<1; else cout<<0; } } } cout<<endl; } }
G. Special Permutation
构造相邻元素差的绝对值在2~4之间的一个序列。
一开始想的是2 4 1 3这样,但难以处理不整除4的情况。后来想到把所有奇数递增,偶数递减地构造,但需要讨论并且交换元素位置...不如官方题解优雅。
#include <bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while(t--) { int n; cin>>n; int i; vector<int>v; v.push_back(0); for(i=1;i<=n;i+=2)v.push_back(i); int temp,odd; if(n&1)temp=n-1,odd=n/2+1; else temp=n,odd=n/2; for(i=temp;i>=2;i-=2)v.push_back(i); if(n<4)cout<<-1<<endl; else if(n==4)cout<<2<<' '<<1<<' '<<4<<' '<<3<<endl; else { cout<<v[odd+1]<<' '<<v[odd+2]<<' '<<v[odd+3]<<endl; if(n&1)swap(v[odd+1],v[odd+2]); else swap(v[odd+1],v[odd+3]),swap(v[odd+2],v[odd+3]); for(i=1;i<=n;i++)cout<<v[i]<<' '; cout<<endl; } } return 0; }