题解 Codeforces Round #615 (Div. 3) (CF1294)

A:判断一下和是不是3的倍数,由于只加不减,所以还要判断有没有大于和的1/3。

 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 }
View Code

B:发现只能向上和向右。所以我们必须保证序列在两维上非降。那么按照x,y升序排序,然后判断一下对于这个点是否存在x比它的x小且y比它的y大,有就是无解。由于字典序要小,所以肯定先右“R”再上“U”。

 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 }
View Code

C:先在√n时间内算出n的因子个数,判断是否有解,注意除去n的1与本身这两个因子。在有解的情况下找出两个小于√n的一个大于√n的(若有解肯定存在)即可。

 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 }
View Code

D:构建mod x的剩余系,每次找到这个剩余系里面最大的加上x即可。注意到最多进行n次操作,所以>=n的其实没啥意义。然后怎么找第一个未出现过的元素:很显然按照我的添加方法肯定每个数只出现一次。所以维护一个set,只要每次把出现过的删掉,输出s.begin()(第一个元素也就是最小的没被删掉的,即还没出现的)即可。

 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 }
View Code

E:这个题的意思就相当于要我们每次可以重置和交换整行,思路肯定是枚举,用桶记一下最小值。然后还是和剩余系的思路一样。

 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 }
View Code

F:明明还剩00:01:06的时候交F可是没交上去呜呜呜。思路是先以1为根找出深度最大的mx1,再以mx1为根找出深度最大的mx2,然后沿着这条路把路上的点标记一下,再找到深度最大的mx3。每次找的时候ans++记录路径长度。由于x个点会有x-1条路,所以最后答案为ans-1.

 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 }
View Code

由于博主已经意识模糊,所以可能会有一些纰漏,请大家指出,谢谢。

这次唯一的收获大概就是一题没挂,于是用大号刷高了小号的rating(雾

大号打Div3不能增加Rating了QAQ,但为了好看还是用小号去刷大号正确率,结果每次都是一遍A,然后提高了小号的Rating……

猜你喜欢

转载自www.cnblogs.com/Kylin-xy/p/12230069.html