题解 Codeforces Round #615 (Div. 3) (CF1294)
A:判断一下和是不是3的倍数,由于只加不减,所以还要判断有没有大于和的1/3。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define it register int 5 #define ct const int 6 #define il inline 7 using namespace std; 8 int T,a,b,c,n,x; 9 namespace io{ 10 il char nc(){ 11 static char buf[100000],*p1=buf,*p2=buf; 12 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 13 } 14 template <class I> 15 il void fr(I &num){ 16 num=0;register char c=nc();it p=1; 17 while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc(); 18 while(c>='0'&&c<='9') num=num*10+c-'0',c=nc(); 19 num*=p; 20 } 21 }; 22 using io :: fr; 23 int main(){ 24 fr(T); 25 while(T--){ 26 fr(a),fr(b),fr(c),fr(n); 27 if((a+b+c+n)%3){puts("NO");continue;} 28 x=(a+b+c+n)/3; 29 if(a>x||b>x||c>x){puts("NO");continue;} 30 puts("YES"); 31 } 32 return 0; 33 }
B:发现只能向上和向右。所以我们必须保证序列在两维上非降。那么按照x,y升序排序,然后判断一下对于这个点是否存在x比它的x小且y比它的y大,有就是无解。由于字典序要小,所以肯定先右“R”再上“U”。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define it register int 5 #define ct const int 6 #define il inline 7 using namespace std; 8 const int N=100005; 9 int T,n,lastx,lasty; 10 bool flag; 11 struct ky{ 12 int x,y; 13 }a[N]; 14 bool cmp(ky p,ky q){ 15 return p.x^q.x?p.x<q.x:p.y<q.y; 16 } 17 int main(){ 18 scanf("%d",&T);it i; 19 while(T--){ 20 scanf("%d",&n); 21 for(i=1;i<=n;++i) scanf("%d%d",&a[i].x,&a[i].y); 22 std::sort(a+1,a+1+n,cmp); 23 flag=0; 24 for(i=1;i<=n;++i) 25 if(a[i].x!=a[i-1].x&&a[i].y<a[i-1].y) flag=1,i=n+1; 26 if(flag){puts("NO");continue;} 27 lastx=0,lasty=0,puts("YES"); 28 for(i=1;i<=n;++i){ 29 for(it j=lastx;j<a[i].x;++j) putchar('R'); 30 for(it j=lasty;j<a[i].y;++j) putchar('U'); 31 lastx=a[i].x,lasty=a[i].y; 32 } 33 putchar('\n'); 34 } 35 return 0; 36 }
C:先在√n时间内算出n的因子个数,判断是否有解,注意除去n的1与本身这两个因子。在有解的情况下找出两个小于√n的一个大于√n的(若有解肯定存在)即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define it register int 5 #define ct const int 6 #define il inline 7 using namespace std; 8 int T,a,b,c,n,x,ans1,ans2,ans3; 9 namespace io{ 10 il char nc(){ 11 static char buf[100000],*p1=buf,*p2=buf; 12 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 13 } 14 template <class I> 15 il void fr(I &num){ 16 num=0;register char c=nc();it p=1; 17 while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc(); 18 while(c>='0'&&c<='9') num=num*10+c-'0',c=nc(); 19 num*=p; 20 } 21 }; 22 using io :: fr; 23 int main(){ 24 fr(T);it i;register long long now=1; 25 while(T--){ 26 fr(n); 27 it x=n,cnt=0;now=1; 28 for(i=2;i*i<=x;++i) 29 if(!(x%i)){ 30 cnt=0; 31 while(!(x%i)) 32 x/=i,++cnt; 33 now*=(cnt+1ll); 34 } 35 if(x>1) now<<=1; 36 now-=2; 37 if(now<3){puts("NO");continue;} 38 x=n,cnt=0,ans1=ans2=0; 39 for(i=2;cnt<2&&i*i<=x;++i) 40 if(!(x%i)) 41 ++cnt,x/=i,cnt==1?ans1=i:(cnt==2?ans2=i:ans3=i); 42 if(cnt==2&&x>ans2&&ans2) 43 puts("YES"),printf("%d %d %d\n",ans1,ans2,x); 44 else puts("NO"); 45 } 46 return 0; 47 }
D:构建mod x的剩余系,每次找到这个剩余系里面最大的加上x即可。注意到最多进行n次操作,所以>=n的其实没啥意义。然后怎么找第一个未出现过的元素:很显然按照我的添加方法肯定每个数只出现一次。所以维护一个set,只要每次把出现过的删掉,输出s.begin()(第一个元素也就是最小的没被删掉的,即还没出现的)即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #include<bitset> 4 #include<set> 5 #include<algorithm> 6 #define it register int 7 #define ct const int 8 #define il inline 9 using namespace std; 10 const int N=1000005; 11 int T,a,b,c,n,x,f[N],maxn; 12 set<int> s; 13 namespace io{ 14 il char nc(){ 15 static char buf[100000],*p1=buf,*p2=buf; 16 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 17 } 18 template <class I> 19 il void fr(I &num){ 20 num=0;register char c=nc();it p=1; 21 while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc(); 22 while(c>='0'&&c<='9') num=num*10+c-'0',c=nc(); 23 num*=p; 24 } 25 }; 26 using io :: fr; 27 bitset<N> vs; 28 int main(){ 29 fr(n),fr(x);it i,nowmax=-1,y;maxn=-1; 30 for(i=0;i<x;++i) f[i]=-1; 31 for(i=0;i<=n;++i) s.insert(i); 32 for(i=1;i<=n;++i){ 33 fr(y),y%=x; 34 f[y]==-1?f[y]=y:f[y]+=x; 35 if(f[y]<=400000) s.erase(f[y]); 36 printf("%d\n",*s.begin()); 37 } 38 return 0; 39 }
E:每一列互不相关,所以可以枚举每一列单独考虑。因为我们可以移动和重置,有的数可以移动但有的必须重置。假设x为第i行j列的数,如果(x+m-1)/m<=n&&x%m==j%m,说明x移动到最终矩阵中的位置的最小次数是(i-(x+m-1)/m+n)%n(+n再%n是为了处理负数)。所以我们把每个最小次数用桶记下来这个最小次数的出现次数,然后枚举最小次数i,求这一列需要的最小次数ans=Min(ans,i+n-s[i]),然后把ans累计入答案。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<vector> 3 #include<algorithm> 4 #define it register int 5 #define ct const int 6 #define il inline 7 using namespace std; 8 const int N=200005; 9 vector<int> a[N]; 10 int s[N],o,n,m; 11 il int Min(ct p,ct q){return p<q?p:q;} 12 namespace io{ 13 il char nc(){ 14 static char buf[100000],*p1=buf,*p2=buf; 15 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 16 } 17 template <class I> 18 il void fr(I &num){ 19 num=0;register char c=nc();it p=1; 20 while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc(); 21 while(c>='0'&&c<='9') num=num*10+c-'0',c=nc(); 22 num*=p; 23 } 24 } 25 using io :: fr; 26 void solve(ct x){ 27 it i,ans=n; 28 for(i=0;i<=n;++i) s[i]=0; 29 for(i=1;i<=n;++i) 30 if(a[x][i]%m==x%m&&(a[x][i]+m-1)/m<=n) ++s[(i-(a[x][i]+m-1)/m+n)%n]; 31 for(i=0;i<=n;++i) ans=Min(ans,i+n-s[i]); 32 o+=ans; 33 } 34 int main(){ 35 fr(n),fr(m);it i,j,x; 36 for(i=1;i<=m;++i) a[i].push_back(0); 37 for(i=1;i<=n;++i) 38 for(j=1;j<=m;++j) 39 fr(x),a[j].push_back(x); 40 for(i=1;i<=m;++i) solve(i); 41 printf("%d",o); 42 return 0; 43 }
F:明明还剩00:01:06的时候交F可是没交上去呜呜呜。思路是先以1为根找出深度最大的mx1,再以mx1为根找出深度最大的mx2,然后沿着这条路把路上的点标记一下,再找到深度最大的mx3。每次找的时候ans++记录路径长度。由于x个点会有x-1条路,所以最后答案为ans-1.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #include<bitset> 4 #include<algorithm> 5 #define it register int 6 #define ct const int 7 #define il inline 8 using namespace std; 9 const int N=1000005; 10 int h[N],nxt[N],adj[N],fa[N],ans,mx1,mx2,mx3,u,v,n,m,t,id,d[N]; 11 bitset<N> vs; 12 namespace io{ 13 il char nc(){ 14 static char buf[100000],*p1=buf,*p2=buf; 15 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 16 } 17 template <class I> 18 il void fr(I &num){ 19 num=0;register char c=nc();it p=1; 20 while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc(); 21 while(c>='0'&&c<='9') num=num*10+c-'0',c=nc(); 22 num*=p; 23 } 24 } 25 using io :: fr; 26 il void dfs(ct x){ 27 d[x]=(vs[x]?1:d[fa[x]]+1); 28 for(it i=h[x],j;i;i=nxt[i]) 29 if((j=adj[i])!=fa[x]) 30 fa[j]=x,dfs(j); 31 } 32 il void add(){ 33 nxt[++t]=h[u],h[u]=t,adj[t]=v,nxt[++t]=h[v],h[v]=t,adj[t]=u; 34 } 35 int main(){ 36 fr(n);it i; 37 for(i=1;i<n;++i) fr(u),fr(v),add(); 38 dfs(1); 39 for(i=1;i<=n;++i){fa[i]=0;if(d[i]>d[mx1]) mx1=i;} 40 dfs(mx1); 41 for(i=1;i<=n;++i) if(d[i]>d[mx2]&&i!=mx1)mx2=i; 42 for(i=mx2;i;i=fa[i]) vs[i]=1,++ans; 43 dfs(mx1); 44 for(i=1;i<=n;++i) if(d[i]>d[mx3]&&i!=mx1&&i!=mx2)mx3=i; 45 for(i=mx3;!vs[i];i=fa[i]) vs[i]=1,++ans; 46 printf("%d\n%d %d %d",ans-1,mx1,mx2,mx3); 47 return 0; 48 }
由于博主已经意识模糊,所以可能会有一些纰漏,请大家指出,谢谢。
这次唯一的收获大概就是一题没挂,于是用大号刷高了小号的rating(雾
大号打Div3不能增加Rating了QAQ,但为了好看还是用小号去刷大号正确率,结果每次都是一遍A,然后提高了小号的Rating……