zoukankan      html  css  js  c++  java
  • 题解 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('
    ');
    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
    ",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
    ",*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
    %d %d %d",ans-1,mx1,mx2,mx3);
    47     return 0;
    48 }
    View Code

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

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

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

  • 相关阅读:
    欧拉公式
    isap的一些想法
    错误合集
    Hello World
    PAT (Advanced Level) Practice 1068 Find More Coins
    PAT (Advanced Level) 1087 All Roads Lead to Rome
    PAT (Advanced Level) 1075 PAT Judge
    PAT (Advanced Level) 1067 Sort with Swap(0, i)
    PAT (Advanced Level) 1017 Queueing at Bank
    PAT (Advanced Level) 1025 PAT Ranking
  • 原文地址:https://www.cnblogs.com/Kylin-xy/p/12230069.html
Copyright © 2011-2022 走看看