Codeforces Round #634 (Div. 3)题解
A. 将一个数拆成两个,两个数不等,求拆分的方法数。
奇数输出n/2,偶数输出n/2-1即可通过。
#include<bits/stdc++.h> #define all(x) x.begin(),x.end() #define fi first #define sd second #define lson (nd<<1) #define rson (nd+nd+1) #define PB push_back #define mid (l+r>>1) #define MP make_pair #define SZ(x) (int)x.size() using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; inline int read(){ int res=0, f=1;char ch=getchar(); while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();} return res*f; } const int MAXN = 200'005; const int MOD = 1000000007; void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;} int mulmod(int a, int b){return 1ll*a*b%MOD;} template<typename T> void chmin(T a, T b){if(a>b)a=b;} template<typename T> void chmax(T a, T b){if(b>a)a=b;} int main(){ int kase=read(); while(kase--){ int n=read(); if(n&1){ cout<<n/2<<endl; }else{ cout<<n/2-1<<endl; } } return 0; }
B. 构造长度为n的,每个长度为a的子串里有b个不同的字母。
先填b个不同的,再填a-b个相同的,每次补上被移走的。
#include<bits/stdc++.h> #define fi first #define sd second #define lson (nd<<1) #define rson (nd+nd+1) #define PB push_back #define MP make_pair #define mid (l+r>>1) #define SZ(x) (int)x.size() using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; inline int read(){ int res=0, f=1;char ch=getchar(); while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();} return res*f; } const int MAXN = 200'005; const int MOD = 1000000007; void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;} int mulmod(int a, int b){return 1ll*a*b%MOD;} void solve(){ int n, a, b; n=read(),a=read(),b=read(); vector<int>cnt(26,0); string s; for(int i=0;i<b;++i){ s+=('a'+i); ++cnt[i]; } for(int i=1;i<=a-b;++i){ s+="a"; ++cnt[0]; } for(int i=a+1;i<=n;++i){ --cnt[s[i-a-1]-'a']; if(cnt[s[i-a-1]-'a']==0){ s+=s[i-a-1]; ++cnt[s[i-a-1]-'a']; }else{ s+="a"; ++cnt[0]; } } cout<<s<<endl; } int main(){ int cases;cases=read(); while(cases--){ solve(); } return 0; }
C. 给一个数组,选择一些数。分成两组,第一组要求数值全都不同,第二组要求全都相同,问组最大能多大。
先统计每一个数值的人数和总类别数。考虑二分答案,check一下即可。
#include<bits/stdc++.h> #define fi first #define sd second #define lson (nd<<1) #define rson (nd+nd+1) #define PB push_back #define MP make_pair #define mid (l+r>>1) #define SZ(x) (int)x.size() using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; inline int read(){ int res=0, f=1;char ch=getchar(); while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();} return res*f; } const int MAXN = 200'005; const int MOD = 1000000007; void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;} int mulmod(int a, int b){return 1ll*a*b%MOD;} void solve(){ int n=read(); vector<int> a(n+1),cnt(n+1,0); for(int i=1;i<=n;++i)a[i]=read(); for(int i=1;i<=n;++i)++cnt[a[i]]; int num=0; for(int i=1;i<=n;++i){ if(cnt[i])++num; } int l=1,r=n/2; int ans=0; while(l<=r){ int ok=0; for(int i=1;i<=n;++i){ if(cnt[i]>=mid){ if(cnt[i]==mid){ if(num>mid){ ok=1; break; } }else{ if(num>=mid){ ok=1; break; } } } } if(ok){ ans=mid; l=mid+1; }else{ r=mid-1; } } cout<<ans<<endl; } int main(){ int cases;cases=read(); while(cases--){ solve(); } return 0; }
D. 给9*9的矩阵,有9个3*3的矩阵。大矩阵保证每一行都是1到9的排列,每一列都是1到9的排列。3*3的网格里,1-9的数都是一个。现在要使得每一行,每一列,每一个3*3的网格里,重复值最多两个,请给出一种构造方案。
将2-9的其中任何一个数字改成1都可以通过。
E. 给你一个数组,每个值都不超过200。求不同的数不超过两个的回文串,这个回文串还要满足AAA...AABBB..BAAAA..AA的形式。
对每一个数统计位置,先更新一遍答案。再枚举一下外层的数字和数字个数(2的倍数),再枚举里面的数,在外面个数变大的时候,双指针移动一下就可以了。(看错题,写了半天最长回文子序列,蠢哭.jpg)。
#include<bits/stdc++.h> #define fi first #define sd second #define lson (nd<<1) #define rson (nd+nd+1) #define PB push_back #define MP make_pair #define mid (l+r>>1) #define SZ(x) (int)x.size() using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; inline int read(){ int res=0, f=1;char ch=getchar(); while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();} return res*f; } const int MAXN = 200'005; const int MOD = 1000000007; void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;} int mulmod(int a, int b){return 1ll*a*b%MOD;} template<typename T> void chmin(T& a, T b){if(a>b)a=b;} template<typename T> void chmax(T& a, T b){if(b>a)a=b;} int n; int a[MAXN]; vector<int> pos[205]; void solve(){ n=read(); for(int i=1;i<=200;++i)pos[i].clear(); for(int i=1;i<=n;++i){ a[i]=read(); pos[a[i]].PB(i); } int ans=0; for(int i=1;i<=200;++i)ans=max(ans,SZ(pos[i])); for(int i=1;i<=200;++i){ if(SZ(pos[i])==0)continue; for(int j=1;j<=200;++j){ if(i==j||SZ(pos[j])==0)continue; int l=0,r=SZ(pos[j])-1; for(int num=2;num<=SZ(pos[i]);num+=2){ while(pos[j][l]<pos[i][num/2-1])++l; while(pos[j][r]>pos[i][SZ(pos[i])-num/2])--r; chmax(ans,num+r-l+1); } } } printf("%d\n",ans); } int main(){ int cases;cases=read(); while(cases--){ solve(); } return 0; }
F. 有一些节点,每个节点有一个颜色(黑色或者白色),每一个节点有且仅有一个出度。现在可以在这些节点上放置机器人,机器人一个时刻走一步。放置的要求是:要求每一个时刻,同一个节点山不能有两个机器人。问最多能放多少个,和在放置最多机器人的情况下,黑色节点上最多能放多少个。
首先有一个观察就是,这个图只能出现简单环或者基环树两种形态的连通块。那么可以发现,能放置的最大数量就是环大小之和,这个很好理解。对于第二个需求,我们显然可以把环山的一些白色节点换成黑色节点,这个可以通过在补图上去bfs实现。或者像我一样,在dfs找环的时候就把这个做完。
#include<bits/stdc++.h> #define all(x) x.begin(),x.end() #define fi first #define sd second #define lson (nd<<1) #define rson (nd+nd+1) #define PB push_back #define mid (l+r>>1) #define MP make_pair #define SZ(x) (int)x.size() using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; inline int read(){ int res=0, f=1;char ch=getchar(); while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();} return res*f; } const int MAXN = 1'000'005; const int MOD = 1000000007; void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;} int mulmod(int a, int b){return 1ll*a*b%MOD;} template<typename T> void chmin(T& a, T b){if(a>b)a=b;} template<typename T> void chmax(T& a, T b){if(b>a)a=b;} vector<string> col; vector<string> dir; vector<vector<int>> In, vis; vector<vector<PII>> cyc; vector<vector<PII>> info; int cy; vector<PII> st; int n, m; int ans[2]; void dfs(int x, int y){ int tx=x,ty=y; if(dir[x][y]=='U')--tx; else if(dir[x][y]=='D')++tx; else if(dir[x][y]=='L')--ty; else ++ty; if(vis[tx][ty]){ if(info[tx][ty]==MP(-1,-1)){ cyc.PB(vector<PII>()); for(int i=vis[tx][ty]-1;i<SZ(st);++i){ info[st[i].fi][st[i].sd].fi=cy; info[st[i].fi][st[i].sd].sd=i-vis[tx][ty]+1; cyc[cy].PB(MP(st[i].fi,st[i].sd)); } int sz=SZ(cyc[cy]); for(int i=vis[tx][ty]-2;i>=0;--i){ int d=vis[tx][ty]-2-i+1; d=sz-d; if(d<0)d=(d%sz+sz)%sz; info[st[i].fi][st[i].sd].fi=cy; info[st[i].fi][st[i].sd].sd=d; if(col[st[i].fi][st[i].sd]=='0'){ col[st[i].fi][st[i].sd]='1'; col[cyc[cy][d].fi][cyc[cy][d].sd]='0'; } } ans[0]+=sz; ++cy; }else{ int tc=info[tx][ty].fi; int pos=info[tx][ty].sd; int sz=SZ(cyc[tc]); for(int i=SZ(st)-1;i>=0;--i){ int d=SZ(st)-i; d=pos-d; while(d<0)d=(d%sz+sz)%sz; info[st[i].fi][st[i].sd].fi=tc; info[st[i].fi][st[i].sd].sd=d; if(col[st[i].fi][st[i].sd]=='0'){ col[st[i].fi][st[i].sd]='1'; col[cyc[tc][d].fi][cyc[tc][d].sd]='0'; } } } }else{ vis[tx][ty]=vis[x][y]+1; st.PB(MP(tx,ty)); dfs(tx,ty); } } void solve(){ cin>>n;cin>>m; col.resize(n); for(int i=0;i<n;++i)cin>>col[i]; dir.resize(n); for(int i=0;i<n;++i)cin>>dir[i]; In.assign(n,vector<int>(m,0)); vis.assign(n,vector<int>(m,0)); for(int i=0;i<n;++i){ for(int j=0;j<m;++j){ if(dir[i][j]=='U')++In[i-1][j]; if(dir[i][j]=='D')++In[i+1][j]; if(dir[i][j]=='L')++In[i][j-1]; if(dir[i][j]=='R')++In[i][j+1]; } } info.resize(n); for(int i=0;i<n;++i){ info[i].resize(m); for(int j=0;j<m;++j){ info[i][j]=MP(-1,-1); } } cy=0; cyc.resize(0); ans[0]=ans[1]=0; for(int i=0;i<n;++i){ for(int j=0;j<m;++j){ if(!In[i][j]){ st.clear(); st.PB(MP(i,j)); vis[i][j]=1; dfs(i, j); } } } for(int i=0;i<n;++i){ for(int j=0;j<m;++j){ if(!vis[i][j]){ ++ans[0]; } if(col[i][j]=='0'){ ++ans[1]; } } } cout<<ans[0]<<" "<<ans[1]<<endl; } int main(){ ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0); int kase;cin>>kase; while(kase--){ solve(); } return 0; }