Codeforces Global Round 24 A-E题题解

A.Doremy's Paint

直接输出1和n即可。

代码:

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. #define fer(i,a,b) for(int i=a;i<=b;i++)  
  4. #define fdr(i,a,b) for(int i=a;i>=b;i--)  
  5. #define int long long  
  6. #define endl '\n'  
  7. #define ll long long  
  8. const int N=2e5+10;  
  9. const int mod=1e9+7;  
  10. signed main()  
  11. {  
  12.     ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);  
  13.     int t;  
  14.     cin>>t;  
  15.     int n;  
  16.     while(t--){  
  17.         cin>>n;  
  18.         cout<<1<<' '<<n<<endl;  
  19.     }  
  20. }  

B.Doremy's Perfect Math Class

找出所有数的最大公约数,然后用所有数中的最大值a[n]除以最大公约数即可得到答案。

代码:

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. #define fer(i,a,b) for(int i=a;i<=b;i++)  
  4. #define fdr(i,a,b) for(int i=a;i>=b;i--)  
  5. #define int long long  
  6. #define endl '\n'  
  7. #define ll long long  
  8. const int N=2e5+10;  
  9. const int mod=1e9+7;  
  10. int gcd(int x,int y){if(y==0) return x;else return gcd(y,x%y);}  
  11.   
  12. int a[N];  
  13. signed main()  
  14. {  
  15.     ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);  
  16.     int t;  
  17.     cin>>t;  
  18.     int n;  
  19.     while(t--){  
  20.         cin>>n;  
  21.         int com=1;  
  22.         fer(i,1,n){  
  23.             cin>>a[i];  
  24.             if(i==1) com=a[1];  
  25.             if(i!=1) com=gcd(com,a[i]);  
  26.         }  
  27.         cout<<a[n]/com<<endl;   
  28.     }   
  29. }  

C.Doremy's City Construction

先对数组进行排序。对于每个数值,求出它的个数(计为mp[x]),小于它的数值的个数(计为pre),大于它的数值的个数(计为suf),取最大的(mp[x]+pre)*suf即可。考虑所有数都相同的特例,发现结果为n/2。//这次比赛时resubmission正确的话会覆盖掉第一次的正确提交,比赛快结束时本想简化一步试试的,结果覆盖掉了之前正确的提交,有点坑。

代码:

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. #define fer(i,a,b) for(int i=a;i<=b;i++)  
  4. #define fdr(i,a,b) for(int i=a;i>=b;i--)  
  5. #define int long long  
  6. #define endl '\n'  
  7. #define ll long long  
  8. const int N=2e5+10;  
  9. const int mod=1e9+7;  
  10. int gcd(int x,int y){if(y==0) return x;else return gcd(y,x%y);}  
  11.   
  12. int a[N];  
  13. signed main()  
  14. {  
  15.     ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);  
  16.     int t;  
  17.     cin>>t;  
  18.     int n;  
  19.     while(t--){  
  20.         cin>>n;  
  21.         map<int,int> mp;  
  22.         map<int,int> mp1;  
  23.         fer(i,1,n) cin>>a[i];  
  24.         sort(a+1,a+1+n);  
  25.         fer(i,1,n) mp[a[i]]++;  
  26.         int ans=0;  
  27.         fer(i,1,n){  
  28.             int x=a[i];  
  29.             int pos=upper_bound(a+1,a+1+n,a[i])-a;  
  30.             mp1[x]++;  
  31.             int pre=i-1,suf=n+1-pos;  
  32.             if(mp1[x]==1) ans=max(ans,(mp[x]+pre)*suf);  
  33.         }  
  34.         if(ans==0) cout<<n/2<<endl;  
  35.         else cout<<ans<<endl;  
  36.     }   
  37. }  

D.Doremy's Pegging Game

引用官方题解的解法

        操作结束的状态是蓝钉不在剩余红钉所组成的多边形内,通过自己尝试,易知取到

连续的⌊n/2⌋(n/2的下取整)个红钉时结束。

        设t=⌊n/2⌋。      

        先考虑n为奇数的情况:

        结束时的状态可以看作是取了 i (t <= i <= n - 2)个连续个红钉和 j (0 <= j <= n - 2 - i)个不与之相邻的红钉。

        现在考虑一下最后取的那个红钉有多少种选法。对于每种连续的 i 个红钉,两侧各自的 i - t 个红钉不能最后选择,否则一定在选这些红钉之前就选够了连续的 t 个红钉。则对于每种连续的 i 个红钉,最后取的那个红钉有 i - 2 * ( i - t ) = 2 * t - i 种选法。

        对于剩下的 i + j - 1 个要选的红钉,顺序无所谓,故乘以 ( i + j - 1)的阶乘。

        再来考虑对于 i 和 j 的组合有多少种选法,对于既定位置的 i 个连续红钉,易知有种 j 的选法。

         对于n边形,显然有n种不同的选择连续 i 个红钉的选法。因此总的选法数目要在上述基础上乘以 n。

        考虑n为偶数的情况:

        显然只比奇数情况多了选 n - 1个红钉的选法,易知有n * ( n - 2 ) ! 种选法。

        于是得出公式

        时间复杂度可视为O(n^2) 。

代码:

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. #define fer(i,a,b) for(int i=a;i<=b;i++)  
  4. #define fdr(i,a,b) for(int i=a;i>=b;i--)  
  5. #define int long long  
  6. #define endl '\n'  
  7. #define ll long long  
  8. const int N=5000+100;  
  9. int gcd(int x,int y){if(y==0) return x;else return gcd(y,x%y);}  
  10.   
  11. int n,mod;  
  12. int c[N][N];  
  13. int fac[N];  
  14. signed main()  
  15. {  
  16.     ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);  
  17.     cin>>n>>mod;  
  18.     fer(i,0,N-1) c[i][0]=1;  
  19.     fer(i,1,N-1){  
  20.         c[i][i]=1;  
  21.         fer(j,i+1,N-1){  
  22.             c[j][i]=(c[j-1][i]+c[j-1][i-1])%mod;  
  23.         }  
  24.     }  
  25.     fac[0]=fac[1]=1;  
  26.     fer(i,2,N-1) fac[i]=fac[i-1]*i%mod;  
  27.       
  28.     int ans=0,t=n/2;  
  29.     fer(i,t,n-1){  
  30.         if((n&1)&&i==n-1) break;  
  31.         int k=n-i-2;  
  32.         if(i==n-1) k=0;  
  33.         fer(j,0,k) ans=(ans+n*(2*t-i)*fac[i+j-1]%mod*c[k][j]%mod)%mod;  
  34.     }  
  35.     cout<<ans<<endl;  
  36. }  

E.Doremy's Number Line

思路引用自Codeforces Global Round 24 A - E - 知乎

先进行特判:

(1)a1>=k一定有解

(2)a1+b1<k一定没有解

(3)n=1且不满足(1)的话也一定没有解

然后对2~n的a,b数组联合进行以a数组为优先的从小到大排序。用pair存储a数组和b数组,方便直接用sort进行排序。

排完序后,对于2,我们直接取a[2],这是到2时能取的最大值。在3~n中,不断迭代,找能被涂色的最大值mx。

找到最大值mx后,判断min( a[1] , mx ) + b[1] 能否 >= k即可。

在找最大值mx时,有以下几个比较点:

(1)到 i 时当前已确定能取的最大值f [ i - 1]

(2)到 i 时新出现的可取的可能最大值,min( f [ i - 1 ],a[ i ] ) + b[ i ]

(3)取a[ i - 1]+b[ i - 1]

(此种取法是因为排序后a[ i ]>a[ i - 1 ],所以可以先取a[ i ] ,再操作 i - 1,保证没有遗漏 )

(4)直接取a[ i ] 

代码:

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. #define int long long  
  4. #define endl '\n'  
  5. #define fer(i,a,b) for(int i=a;i<=b;i++)  
  6. #define xx first  
  7. #define yy second  
  8. #define P pair<int,int>  
  9. const int N=1e5+10;  
  10. const int INF=1e9+10;  
  11.   
  12. int n,k;  
  13. int f[N];  
  14. int a[N],b[N];  
  15. P p[N];  
  16.   
  17. void solve(){  
  18.     if(p[1].xx>=k){  
  19.         puts("YES");  
  20.         return;  
  21.     }  
  22.     if(n==1){  
  23.         puts("NO");  
  24.         return;  
  25.     }  
  26.     if(p[1].xx+p[1].yy<k){  
  27.         puts("NO");  
  28.         return;  
  29.     }  
  30.     sort(p+2,p+n+1);  
  31.     f[2]=p[2].xx;  
  32.     fer(i,3,n){  
  33.         f[i]=max(f[i-1],min(f[i-1],p[i].xx)+p[i].yy);  
  34.         f[i]=max(f[i],p[i-1].xx+p[i-1].yy);  
  35.         f[i]=max(f[i],p[i].xx);  
  36.     }  
  37.     int res=min(f[n],p[1].xx)+p[1].yy;  
  38.     if(res>=k) puts("YES");  
  39.     else puts("NO");  
  40.     return;  
  41. }  
  42. signed main(){  
  43.     ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);  
  44.     int t;  
  45.     cin>>t;  
  46.     while(t--){  
  47.         cin>>n>>k;  
  48.         fer(i,1,n){  
  49.             cin>>a[i]>>b[i];  
  50.             p[i].xx=a[i],p[i].yy=b[i];  
  51.         }  
  52.         solve();  
  53.     }      
  54. }  












 

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值