练习记录-cf-div2-Codeforces Round 870 (A-D)
这次写的也是比较快!rank305 虽然D简单,但是写出来了就算胜利!
A. Trust Nobody
题意:给出n个人,他们会说多少人是说谎的,你要找出这个人数
思路: n最多只有100个,我枚举说谎的人有i个,对说话小于等于i的做前缀和,这个几个人都是说真话,记录前缀和sum,n-sum就是说谎人数,如果n-sum==i 就是符合的 否则输出-1

#include<bits/stdc++.h> #define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) using namespace std; typedef long long ll; const ll MAXN = 3e5+7; const ll mod =1e9+7; const ll inf =0x3f3f3f3f; int a[MAXN],pre[200]; const ll INF =0x3f3f3f3f3f3f3f3f; void solve(){ int n;cin>>n; for(int i=0;i<=n;i++) pre[i]=0; for(int i=1;i<=n;i++) { cin>>a[i]; pre[a[i]]++; } int sum=0; for(int i=0;i<=n;i++){ sum+=pre[i]; if(n-sum==i){ cout<<i<<"\n"; return; } } cout<<"-1\n"; } signed main(){ close; int t;cin>>t; while(t--) solve(); }
* 这个A还是有一点点思维量的,感觉可以放在B的那种
B. Lunatic Never Content
题意: 找出一个最大的数x,让对称的数列元素modx相等
思路: 当给出两个数 比如说 3 7 那么最大的数就是abs(3-7)=4,那么2也是可以的 1也是
对于每一组元素,都可以求出最大的数,然后进行gcd即可

#include<bits/stdc++.h> #define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) using namespace std; typedef long long ll; #define int long long const ll MAXN = 3e5+7; const ll mod =1e9+7; const ll inf =0x3f3f3f3f; int a[MAXN],pre[200]; const ll INF =0x3f3f3f3f3f3f3f3f; void solve(){ int n;cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; } int l=1,r=n; int mins=0; while(l<r){ int k=abs(a[r]-a[l]); if(k==0){ l++; r--; continue; } if(mins==0){ mins=k; } else{ mins=__gcd(mins,k); } l++; r--; } cout<<mins<<"\n"; } signed main(){ close; int t;cin>>t; while(t--) solve(); }
C. Dreaming of Freedom
这题和HZNU 2023的校赛一样ww完全一致吧,当时机智的我给团队贡献了7发wa哈哈哈
题意: n个人投票,投给m个人,是否存在永远平局的情况
思路:首先,如果人数小于投票的位置,比如n=3,m=5, 那么永远给3个位置一人一票就是平局(特判下1 一定出结果)
其次,如果m比n的某个因子大,也是可以的。比如n=6,m=4 2是n的因子,m>=2,因此可以全投给两个位置保持平局
枚举i (2~m) 如果其中一个数能整除n 那就退出,i*i>n时退出(后面的情况是对称的) 因此时间复杂度为根号n(我们校赛刚好卡这个根号来着www

#include<bits/stdc++.h> #define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) using namespace std; typedef long long ll; #define int long long const ll MAXN = 3e5+7; const ll mod =1e9+7; const ll inf =0x3f3f3f3f; int a[MAXN],pre[200]; const ll INF =0x3f3f3f3f3f3f3f3f; void solve(){ int n,m;cin>>n>>m; if(n==1){ cout<<"Yes\n"; } else if(n<=m){ cout<<"No\n"; } else{ int flag=0; for(int i=2;i<=m;i++){ if(i*i>n) break; if(n%i==0) { flag=1; break; } } if(flag) cout<<"No\n"; else cout<<"Yes\n"; } } signed main(){ close; int t;cin>>t; while(t--) solve(); }
D. Running Miles
题意:路长为n 每一个单位有一个景点,好看度为bi,你可以选择开始坐标l和结束坐标r,答案的值就是 你包含的坐标中 最大的三个好看度-(r-l)
思路:裸的dp,记录dp[i][4],0表示不取 1表示取了一个。。。。。
dp[i][0] 只能从上一位0中传递来,是相等的 表示一直不取
dp[i][1] 可以是这一位开始选,也可以是上一位的1继承下来然后-1(算上路径长度)
dp[i][2] 可以是这一位加上一个再-1,也可以是上一位继承然后-1
......
最后遍历一遍dp[i][3] 取最大值即可
居然会有这么简单的2000!

#include<bits/stdc++.h> #define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) using namespace std; typedef long long ll; const ll MAXN = 3e5+7; const ll mod =1e9+7; const ll inf =0x3f3f3f3f; #define int long long int a[MAXN],dp[MAXN][4]; const ll INF =0x3f3f3f3f3f3f3f3f; void solve(){ int n;cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; dp[i][0]=0; dp[i][1]=0; dp[i][2]=0; dp[i][3]=0; } for(int i=1;i<=n;i++){ dp[i][0]=dp[i-1][0]; dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]-1); if(i==1) continue; dp[i][2]=max(dp[i-1][1]+a[i]-1,dp[i-1][2]-1); if(i==2) continue; dp[i][3]=max(dp[i-1][2]+a[i]-1,dp[i-1][3]-1); } int maxs=0; for(int i=1;i<=n;i++){ // cout<<dp[i][3]<<"\n"; maxs=max(maxs,dp[i][3]); } cout<<maxs<<"\n"; } signed main(){ close; int t;cin>>t; while(t--) solve(); }
E看起来也是dp 再说再说