Codeforces Round 911 (Div. 2)
Codeforces Round 911 (Div. 2)
A - Cover in Water
思路:发现若有连续的三个...,可以通过两次操作将两边的水填满,对于中间的位置自动产水再移走去填补其他空,那么只需要两次
其余的情况则需要一一操作填满空
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 #define double long double typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; void solve(){ int n; string s; cin>>n>>s; int ma=0,cnt=0,all=0; for(int i=0;i<n;++i){ if(s[i]=='.')cnt++,ma=max(ma,cnt),all++; else cnt=0; } if(ma>=3)cout<<2<<'\n'; else cout<<all<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; cin>>t; while(t--){ solve(); } return 0; }
B - Laura and Operations
思路:若全转变为a,假设b>=c,可先对b、c操作c次,三个数变为a+c、b-c、0,可以通过进行 减ab加c 和 减bc从加a 两次操作使得三个数变为a+c、b-c-2、0,那么只需要判断b-c是否为偶数即可,全转变为a或b或c都是同理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 #define double long double typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; void solve(){ int a,b,c; vector<int>ans(3,0); cin>>a>>b>>c; if(abs(b-c)%2==0)ans[0]=1; if(abs(a-c)%2==0)ans[1]=1; if(abs(a-b)%2==0)ans[2]=1; for(int i=0;i<3;++i)cout<<ans[i]<<' '; cout<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; cin>>t; while(t--){ solve(); } return 0; }
C - Anji's Binary Tree
思路:从根节点dfs跑一次,可以剪下枝,当前次数已经大于答案了就不用继续了
或者dp维护从i到达叶子节点需要的最少次数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 #define double long double typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; int n,ans,tes; string s; vector<vector<int>>ve; vector<int>out; void dfs(int u){ if(tes>=ans)return; if(!out[u]){ ans=min(ans,tes); return ; } if(ve[u][0]){ if(s[u]!='L'){ tes++; dfs(ve[u][0]); tes--; }else dfs(ve[u][0]); } if(ve[u][1]){ if(s[u]!='R'){ tes++; dfs(ve[u][1]); tes--; }else dfs(ve[u][1]); } } void solve(){ // int n; // string s; ans=INF; cin>>n>>s; s=" "+s; ve=vector<vector<int>>(n+1,vector<int>(2)); out=vector<int>(n+1); for(int i=1;i<=n;++i){ cin>>ve[i][0]>>ve[i][1]; out[i]+=(int)(ve[i][0]!=0)+(int)(ve[i][1]!=0); } tes=0; dfs(1); cout<<ans<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; cin>>t; while(t--){ solve(); } return 0; }
D - Small GCD
思路:求Σf(ai,aj,ak),其实就是所有gcd(ai,aj)的贡献,那么ijk的顺序就不重要了,首先可以将a排序。
可以枚举j,求出Σgcd(ai,aj),i<j,且k的个数等于Σgcd(ai,aj)贡献的次数,那么答案就是Σgcd(ai,aj)*(n-i),i<j
考虑到复杂度,怎么求Σgcd(ai,aj),i<j 呢?
引入欧拉反演
n/d表示n以内的数中为d的倍数的数量,在本题中可以维护a1~ai的所有数中为d的倍数的数量cnt[d]
则有
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 #define double long double typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=1e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; int cnt,primes[N],phi[N]; bool st[N]; int n; void get_phi(int n){ phi[1]=1; for(int i=2;i<=n;++i){ if(!st[i])phi[i]=i-1,primes[cnt++]=i; for(int j=0;primes[j]*i<=n;++j){ int t=i*primes[j]; st[t]=true; if(i%primes[j]==0){ phi[t]=phi[i]*primes[j]; break; } else phi[t]=phi[i]*(primes[j]-1); } } } void solve(){ cin>>n; vector<int>a(n+1),num(N); for(int i=1;i<=n;++i)cin>>a[i]; sort(a.begin()+1,a.end()); int ans=0; for(int i=1;i<n;++i){ int s=0,x=a[i]; for(int j=1;j*j<=x;++j){ if(x%j)continue; s+=phi[j]*num[j]++; if(j*j!=x)s+=phi[x/j]*num[x/j]++; } ans+=s*(n-i); } cout<<ans<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; cin>>t; get_phi(100000); while(t--){ solve(); } return 0; }