Codeforces Round 1012 (Div. 2)
A
直接看一看s%(x+y)的余数即可,简单的数学推导
#include<bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while(t--) { int x,y,a; cin>>x>>y>>a; int k=a%(x+y); if(x>k) cout<<"NO"<<endl; else cout<<"YES"<<endl; } return 0; }
B
一开始的想法是类似于一个dp看看这个1的左侧和上侧有没有1,如果有是对的不然直接退出
但是可能会跳出,test3就wa了
重新思考一下,发现充要条件是它的上方或左侧全部都是1
#include<bits/stdc++.h> using namespace std; const int N=55; char g[N][N]; void slove() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cin>>g[i][j]; } } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(g[i][j]=='1') { bool st1=1,st2=1; for(int k=1;k<=i;k++) { if(g[k][j]=='0') { st1=0; break; } } for(int k=1;k<=j;k++) { if(g[i][k]=='0') { st2=0; break; } } if(st1==0&&st2==0) { cout<<"NO"<<endl; return; } } } } cout<<"YES"<<endl; return; } int main() { int t; cin>>t; while(t--) slove(); return 0; }
C
就是动态维护一下起点到哪些桌子点最小的点,和到座位最小的点,可以用小根堆维护
也可以用数组加一个判重数组维护,本人不太会写重载函数所以使用数组
到这里其实就不会写了,剩下的都是看题解补的题
#include<bits/stdc++.h> using namespace std; vector<array<int,3>> b; void init() { int m=320; for(int i=0;i<m;i++) { for(int j=0;j<m;j++) { int x=i*3+1,y=j*3+1; b.push_back({x+y-1,x,y}); b.push_back({x+y,x,y+1}); b.push_back({x+y,x+1,y}); b.push_back({x+y+3,x+1,y+1}); } } sort(b.begin(),b.end()); } void slove() { int n; cin>>n; vector<int> a(n); for(int i=0;i<n;i++) cin>>a[i]; int m=sqrt(2*n)+3; vector<vector<int>> f(m*3,vector(m*3,0)); vector<vector<int>> g(m,vector(m,0)); int k1=0,k0=0; for(int i=0;i<n;i++) { int x,y; if(a[i]) { while(f[b[k1][1]][b[k1][2]])k1++; x=b[k1][1],y=b[k1][2]; } else { while(g[b[k0][1]/3][b[k0][2]/3]) k0++; x=b[k0][1],y=b[k0][2]; } f[x][y]=1; g[x/3][y/3]=1; cout<<x<<' '<<y<<endl; } return; } int main() { init(); int q; cin>>q; while(q--) slove(); return 0; }
D
构造题,我们想取一个质数让 i=1时它是质数,但是当i=2时它肯定不是质数了,那么i=3时
希望它是就选取2为1和3的等差中项即可
由于勃兰特---切比雪夫定理和题意我们只需要在n/3何2n/3之间找一个质数即可
#include<bits/stdc++.h> using namespace std; const int N=100010; int prime[N],cnt; bool st[N]; void init() { for(int i=2;i<=N;i++) { if(st[i]==0) prime[cnt++]=i; for(int j=0;prime[j]<=N/i;j++) { st[prime[j]*i]=true; if(i%prime[j]==0) break; } } } void slove() { int n; cin>>n; int l=max(1,n/3); int r=(2*n)/3; int p=2; for(int i=0;i<=cnt;i++) { if(prime[i]>=l&&prime[i]<=r) { p=prime[i]; break; } } vector<int> ans; ans.push_back(p); for(int i=1;;i++) { if(p-i>=1&&p+i<=n) { ans.push_back(p-i); ans.push_back(p+i); } else if(p-i>=1) ans.push_back(p-i); else if(p+i<=n) ans.push_back(p+i); else break; } for(int t : ans) cout<<t<<' '; cout<<endl; return; } int main() { init(); //for(int i=0;i<=20;i++) cout<<prime[i]<<endl; int t; cin>>t; while(t--) slove(); return 0; }
E1
其实想法和答案以经很接近了,就是找每一个数变为0的步数然后求一个最大值,但是没往深想
其实题干中已经有提示了,题一定有解,sum(b)>=sum(a);说明一个数变为0的步数一定和sum(b)
和sum(a)有关,我们发现经过第一次操作后大数变为其和小数的差,小数直接变为0,然后a错位减
经过一些推导发现什么时候sum(b)>sum(a)时其就为0了
using namespace std; typedef long long LL; int n; LL c_sum(LL p[],int l,int r) { if(l>r)return p[n-1]-p[l-1]+p[r]; else { if(l-1>=0) return p[r]-p[l-1]; else return p[r]; } } void slove() { int k; scanf("%d%d",&n,&k); vector<int> a(n); vector<int> b(n); LL p[n]; for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<n;i++) scanf("%d",&b[i]); for(int i=0;i<n;i++) { p[i]=a[i]-b[i]; if(i) p[i]+=p[i-1]; } vector<int> c(n,1); for(int i=n-1;i>=0;i--) { int len=1; while(c_sum(p,i,(i+len-1)%n)>0) { len+=c[(i+len)%n]; } c[i]=len; } int res=-1; for(int i=0;i<n;i++) res=max(c[i],res); printf("%d\n",res); return; } int main() { int t; scanf("%d",&t); while(t--) slove(); return 0; }