題解 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:每一列互不相關,所以可以枚舉每一列單獨考慮。因為我們可以移動和重置,有的數可以移動但有的必須重置。假設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累計入答案。

 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……


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM