感觉这次CD题比之前简单?
A. Download More RAM
题意:给n组数据和当前值k,k大于 ai 就可增加 bi ,问最后k最大值。
解:带水题,看代码即可。
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxx 200005 #define eps 0.00000001 #define inf 0x7fffffff //#define int long long int n,k; int a[maxx],b[maxx]; signed main() { int T; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&b[i]); vector<pair<int,int> > v; for(int i=1;i<=n;i++) v.push_back(make_pair(a[i],b[i])); sort(v.begin(),v.end()); for(auto [ai,bi]:v){ if(k>=ai) k+=bi; else break; } printf("%d\n",k); } return 0; }
B. GCD Arrays
题意:给出一组连续的自然数,每次可以抓两个数把它们变成它们的乘积,问执行k次操作后整组数的gcd有没有可能不是1。
解:求一下不是1最少要执行几次。相邻的两个数两两互质,所以要使它们不再相邻至少执行n/2次。执行之后会有若干个偶数和可能留下的一个奇数,如果留下一个奇数加一次操作即可。
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxx 200005 #define eps 0.00000001 #define inf 0x7fffffff //#define int long long int n,k; int l,r; signed main() { int T; scanf("%d",&T); while(T--){ scanf("%d%d%d",&l,&r,&k); int temp=(r-l+1); int ans=0; if(temp==1){ if(l==1) printf("NO\n"); else printf("YES\n"); continue; } else if(temp%2==0) ans=temp/2; else{ if(l%2==0) ans=temp/2; else ans=(temp+1)/2; } if(k<ans) printf("NO\n"); else printf("YES\n"); } return 0; }
C. Meximum Array
题意:给出[0,n]之间的n个数,每次选前k个取mex加入b,然后将k个数从原数组中删除。求字典序最大的b。
解:每次挑最大的mex加入b,并留下尽可能多的数。直接解法是每次求出最大mex,找到[0,mex]中数的最大位置pos,下一次从pos+1开始,然后把[1,pos]对应删除。实测会T。
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxx 200005 #define eps 0.00000001 #define inf 0x7fffffff //#define int long long int n; int a[maxx]; signed main() { int T; scanf("%d",&T); while(T--){ scanf("%d",&n); set<int> cnt[n+1]; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); cnt[a[i]].insert(i); } vector<int> ans; int pos=1; while(pos<=n){ int mex=0; while(!cnt[mex].empty()) { pos=max(pos,*cnt[mex].begin()); mex++; } ans.push_back(mex); for(int i=1;i<=pos;i++){ cnt[a[i]].erase(i); } pos++; } printf("%d\n",ans.size()); for(auto i:ans) printf("%d ",i); printf("\n"); } return 0; }
不加数据结构的话只能一个一个找过来求mex(加数据结构我也不会)。考虑能否直接判断这个位置已经取到最大的mex。当后续没有mex出现时,就可以开始找下一段的mex了。找下一段的mex需要把前面的删掉,因此还要保存现在出现的数,到时候再清空。
其实不太理解这玩意快在哪但它过了。
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxx 200005 #define eps 0.00000001 #define inf 0x7fffffff //#define int long long int n; int a[maxx]; int cnt[maxx]={0}; signed main() { int T; scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); cnt[a[i]]++; } vector<int> ans; set<int> s; int mex=0; for(int i=1;i<=n;i++){ cnt[a[i]]--; s.insert(a[i]); while(s.count(mex)) mex++; if(cnt[mex]==0){ ans.push_back(mex); mex=0; s.clear(); } } printf("%d\n",ans.size()); for(auto i:ans) printf("%d ",i); printf("\n"); } return 0; }
D. Peculiar Movie Preferences
题意:给出n个不超过3的字符串,问是否能够挑出几个按顺序拼成回文串。
解:这玩意比C简单,因为它每个长度都不超过3,变成了带分类讨论。
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxx 200005 #define eps 0.00000001 #define inf 0x7fffffff //#define int long long int n; signed main() { int T; cin>>T; while(T--){ cin>>n; map<string,int> m1; map<string,int> m2; string t[n+1]; for(int i=1;i<=n;i++){ cin>>t[i]; m1[t[i]]=i; if(t[i].length()==3) m2[t[i].substr(1,2)]=i; } int flag=0; for(int i=1;i<=n;i++){ int len=t[i].length(); if(len==1){ flag=1; break; } if(len==2) { string b = t[i]; reverse(b.begin(), b.end()); if (m1[b]||m2[b]>=i) { flag = 1; break; } } if(len==3){ string b = t[i]; reverse(b.begin(), b.end()); if (m1[b]) { flag = 1; break; } b = t[i].substr(0,2); reverse(b.begin(), b.end()); if (m1[b] >= i) { flag = 1; break; } } } if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }
E. Grid Xor
题意:有一个n*n的矩阵,n为偶数,将其每个格子的值替换为相邻四个格子值的异或和。现给出异或和矩阵,求原矩阵整个异或和。
解:一开始读假题了,但思路差不多。异或具有结合律,因此方法是找几个位置,使得这几个位置能覆盖整个矩阵,使得每个数字被覆盖奇数次,然后将这几个位置的值异或起来。现在考虑怎么找这些位置。这题读起来很熟,像紫书上奶牛翻砖块那题,就是中间那块不用翻。于是(很不要脸地)找了个奶牛刨地板的代码打表试图找规律,规律没找到,但发现第一行每一种可能都能解出解法,这个解是O(n)的。那当场跑一个吧。
打表代码:
//#include<bits/stdc++.h> //using namespace std; //#define ll long long //#define maxx 200005 //#define eps 0.00000001 //#define inf 0x7fffffff ////#define int long long //int n; //int a[1005][1005]; //signed main() { // int T; // scanf("%d",&T); // while(T--){ // scanf("%d",&n); // for(int i=1;i<=n;i++) // for(int j=1;j<=n;j++) // scanf("%d",&a[i][j]); // int ans=0; // for(int i=1;i<=n;i+=2) // for(int j=1;j<=n;j++) // ans^=a[i][j]; // printf("%d\n",ans); // } // return 0; //} #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define ll long long #define inf 1000000000 using namespace std; int n,m,ed; int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0}; bool a[16][16],t[16][16],op[16][16]; void operate(int x,int y){ op[x][y]=1; for(int k=0;k<4;k++) { int nowx=x+xx[k],nowy=y+yy[k]; if(nowx<1||nowy<1||nowx>n||nowy>m)continue; t[nowx][nowy]^=1; } } void solve(int x){ memset(op,0,sizeof(op)); int tot=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) t[i][j]=a[i][j]; for(int i=1;i<=m;i++) if((1<<(i-1))&x){ operate(1,i); } for(int i=2;i<=n;i++) for(int j=1;j<=m;j++){ if(t[i-1][j]) operate(i,j); } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(t[i][j])return; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) printf("%d ", op[i][j]); printf("\n"); } printf("\n"); } int main(){ int x; scanf("%d",&x); for(int cnt=2;cnt<=x;cnt+=2) { printf(" %d\n",cnt); n = cnt; m = cnt; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) a[i][j] = 1; ed = (1 << m) - 1; solve(0); // for (int i = 0; i <= ed; i++) // solve(i); } return 0; }
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxx 1005 #define eps 0.00000001 #define inf 0x7fffffff //#define int long long int n; int aa[maxx][maxx]; int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0}; bool a[maxx][maxx],op[maxx][maxx]; void operate(int x,int y){ op[x][y]=1; for(int k=0;k<4;k++){ int nowx=x+xx[k],nowy=y+yy[k]; if(nowx<1||nowy<1||nowx>n||nowy>n)continue; a[nowx][nowy]^=1; } } void solve(){ for(int i=2;i<=n;i++) for(int j=1;j<=n;j++){ if(a[i-1][j]) operate(i,j); } } signed main() { int T; scanf("%d",&T); while(T--){ memset(op,0,sizeof(op)); scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&aa[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=1; solve(); int ans=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(op[i][j]) ans^=aa[i][j]; printf("%d\n",ans); } return 0; }