链接:https://codeforces.com/gym/240668
A - Olesya and Rodion - [水]
题解:注意到 $t$ 的范围是 $[2,10]$,对于位数小于 $2 \times 3 \times \cdots \times 10 = 3628800$ 的数,暴力枚举去找;否则就直接在 $3628800$ 后面补零即可。
AC代码:
#include<bits/stdc++.h> using namespace std; int n,t; int p10[8]; int main() { ios::sync_with_stdio(0); cin>>n>>t; if(n>=7) { cout<<3628800; for(int i=8;i<=n;i++) cout<<0; cout<<endl; } else { p10[0]=1; for(int i=1;i<8;i++) p10[i]=p10[i-1]*10; bool ok=0; for(int x=p10[n-1];x<p10[n];x++) { if(x%t==0) { cout<<x<<endl; ok=1; break; } } if(!ok) cout<<-1<<endl; } }
B - Kolya and Tanya - [组合数]
题解:对于一个等边三角形上的三个人,有 $20$ 种方案使得和不等于 $6$,有 $7$ 种方案使得和等于 $6$,然后很容易得到公式 $\sum_{i=1}^{n} C_{n}^{i} \cdot 20^i \cdot 7^{n-i}$。
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; int n; ll fpow(ll a,ll n) { ll res=1,base=a%mod; while(n) { if(n&1) res*=base, res%=mod; base*=base, base%=mod; n>>=1; } return res%mod; } ll inv(ll n){return fpow(n,mod-2);} int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); cin>>n; ll ans=0; ll C=1ll, A=1ll, B=fpow(7ll,n); for(int i=1;i<=n;i++) { C=C*(n+1-i), C%=mod; C=C*inv(i), C%=mod; A*=20ll, A%=mod; B*=inv(7), B%=mod; ans+=((C*A)%mod)*B%mod, ans%=mod; } cout<<ans<<endl; }
C - Marina and Vasya - [字符串]
题解:
要有 $t$ 个不同字符,就是要有 $n-t$ 个相同字符;对于 $s_1,s_2$ 两个字符串,如果存在 $s_1[i] = s_2[i]$ 就尽量让 $s_3[i]$ 也是这个字符。如果直接就能把 $n-t$ 个要求相同的字符全搞定了,剩下的就可以乱放。
如果还剩下来 $n-t-same$(此处 $same$ 代表 $s_1,s_2$ 中相同位置且相同字符的数目),要求有这么多个相同字符。那记 $diff$ 代表 $s_1,s_2$ 中相同位置但不同字符的数目,讨论一下 $2(n-t-same)$ 与 $diff$ 的关系即可。
AC代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+5; int n,t; string s1,s2,s3; bool f[maxn]; int same,diff; inline char Find(char x,char y) { if(x!=‘a‘ && y!=‘a‘) return ‘a‘; if(x!=‘b‘ && y!=‘b‘) return ‘b‘; if(x!=‘c‘ && y!=‘c‘) return ‘c‘; } int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); cin>>n>>t; t=n-t; cin>>s1>>s2; for(int i=0;i<n;i++) s3+=‘0‘; int diff=0; for(int i=0;i<n;i++) { if(s1[i]!=s2[i]) diff++; if(s1[i]==s2[i] && t>0) { s3[i]=s1[i]; t--; } } if(t>0) { if(2*t>diff) s3="-1"; else { int cnt=0; for(int i=0;i<n;i++) { if(s3[i]!=‘0‘) continue; s3[i]=s1[i], cnt++; if(cnt==t) break; } cnt=0; for(int i=0;i<n;i++) { if(s3[i]!=‘0‘) continue; s3[i]=s2[i], cnt++; if(cnt==t) break; } for(int i=0;i<n;i++) { if(s3[i]!=‘0‘) continue; s3[i]=Find(s1[i],s2[i]); } } } else { for(int i=0;i<n;i++) { if(s3[i]!=‘0‘) continue; s3[i]=Find(s1[i],s2[i]); } } cout<<s3<<endl; }
D - Dima and Lisa - [简单数论]
题解:
有一个命题:不小于 $6$ 的偶数都能表示成两个质数的和,然后 $4$ 可以表示成 $2+2$。
所以,我们只要让 $p_1 = 3$,那么剩下来 $n-3$ 必为偶数,就能找到两个质数加起来等于它,这要求最少也要筛 $1 \sim 5e8$ 的素数,会MLE。
因此,我们可以找出 $1e8,2e8,\cdots,9e8$ 这些数字附近的一个素数,然后例如 $n = 5e8+6e7$ 时,我们可以选 $p_1 = 5e8+9$,这样剩下来 $n - (5e8+9)$ 这个数的范围就保证在 $1 \sim 1e8$ 之间,然后我们只需要筛 $1 \sim 1e8$ 之间的素数就可以了。
AC代码:
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> P; int n; const int MAX=1e8+50; int cnt,prime[MAX/10]; bool isPrime[MAX+5]; void Screen() //欧拉筛法求素数 { cnt=0; memset(isPrime,1,sizeof(isPrime)); isPrime[0]=isPrime[1]=0; for(int i=2;i<=MAX;i++) { if(isPrime[i]) prime[cnt++]=i; for(int j=0;j<cnt;j++) { if(i*prime[j]>MAX) break; isPrime[i*prime[j]]=0; if(i%prime[j]==0) break; } } } P Find(int sum) { int p1=0, p2=cnt-1; while(p1<=p2 && prime[p1]+prime[p2]!=sum) { if(prime[p1]+prime[p2]>sum) p2--; else p1++; } return make_pair(prime[p1],prime[p2]); } int D[9]={(int)9e8-37,(int)8e8-1,(int)7e8+1,(int)6e8+1,(int)5e8+9,(int)4e8+9,(int)3e8+7,(int)2e8-9,(int)1e8+7}; int main() { Screen(); cin>>n; if(n==3) { printf("1\n"); printf("3\n"); return 0; } if(n==4) { printf("2\n"); printf("2 2\n"); return 0; } if(n==5) { printf("2\n"); printf("2 3\n"); return 0; } if(n==6) { printf("3\n"); printf("2 2 2\n"); return 0; } for(int i=0;i<9;i++) { if(n-D[i]>=4) { P res=Find(n-D[i]); printf("3\n"); printf("%d %d %d\n",D[i],res.first,res.second); return 0; } } P res=Find(n-3); printf("3\n"); printf("3 %d %d\n",res.first,res.second); }
E - Anton and Ira - [贪心]
原文地址:https://www.cnblogs.com/dilthey/p/10542910.html