• Codeforces Round #480 (Div. 2)


    A题:Links and Pearls

    只要-的数量能整除o的数量就可,注意特判0

    没啥好写的

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cmath>
     6 #include <bitset>
     7 typedef long long ll;
     8 using namespace std;
     9 char s[110];
    10 int len0=0,len1=0,len=0;
    11 int main(){
    12     scanf("%s",s+1);
    13     len=strlen(s+1);
    14     for(int i=1;i<=len;i++){
    15         if(s[i]=='-') len0++;
    16         else len1++;
    17     }
    18     if(len0==0) printf("YES
    ");
    19     else{
    20         if(len1==0){printf("YES
    ");return  0;}
    21         if(len0%len1==0){printf("YES
    ");}
    22         else printf("NO
    ");
    23     }
    24     return 0;
    25 }
    View Code

    B题:Marlin

    这也是一个简单构造题

    只要围绕x轴对称,或者围绕着y轴对称即可

    ——————————————这样就很容易想了,如果是偶数的话我们只要从左往右依次上下填满就ok了,这样就可以填偶数的————————————————

    ——————————————由于中间这个是奇数的,我们只需要把第二排中间先填上,然后按照奇数对称即可———————————————————————

    下面是代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cmath>
     6 typedef long long ll;
     7 using namespace std;
     8 int n,k;
     9 char s[8][120];
    10 int main(){
    11     scanf("%d%d",&n,&k);
    12     printf("YES
    ");
    13     for(int i=1;i<=4;i++)
    14         for(int j=1;j<=n;j++)
    15             s[i][j]='.';
    16     if(k%2==0){
    17         for(int j=2;j<=n-1;j++){
    18             for(int i=2;i<=3;i++){
    19                 if(k>0){
    20                     k--;
    21                     s[i][j]='#';
    22                 }
    23             }
    24         }
    25     }else{
    26         k--;s[2][(n/2)+1]='#';
    27         int q=(n-3)/2,t=(n/2)+1;
    28         //cout<<q<<endl;
    29         for(int i=2;i<=3;i++){
    30             for(int j=1;j<=q;j++){
    31                 if(k>0){
    32                     k--;k--;
    33                     s[i][t-j]='#';
    34                     s[i][t+j]='#';
    35                 }
    36             }
    37         }
    38     }
    39     for(int i=1;i<=4;i++){
    40         for(int j=1;j<=n;j++) printf("%c",s[i][j]);
    41         printf("
    ");
    42     }
    43     return 0;
    44 }
    View Code

    ————————————————————————————————————————————

    这个n是奇数其实是关键所在,是应该一下子就要反应过来的!

    其他按照对称性就ok

    这个n是奇数的作用就是保证奇数次能有位置放

    ————————————————————————————————————————————

    这道题怎样搞都可以,主要是发现一下这个的对称性!!!!!!!!!!!

    当时思考这道题是脑子是乱的,连简单的对称性都看不出

    其实还有一个原因是我对这个图形一点都不敏感,这个才是问题的关键!!!!!!!!!!!

    ————————————————————————————————————————————

    C题:Posterized

    ————————————————————————————————————————————

    这个题就更简单了,我感觉思维就很明确的那种,就是贪心,直接往前面找,然后复杂度是o(n*255)

    一开始还读错了题,看来读题是真的很重要重要

    下面是代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cmath>
     6 typedef long long ll;
     7 using namespace std;
     8 const int maxn=(int)(1e5+1000);
     9 int n,k;
    10 int num[maxn];
    11 int vis[270];
    12 int las[maxn];
    13 int main(){
    14     scanf("%d%d",&n,&k);
    15     for(int i=1;i<=n;i++) scanf("%d",&num[i]);
    16     for(int i=1;i<=n;i++){
    17         if(vis[num[i]]!=0){
    18             for(int j=num[i];j>=max(num[i]-k+1,0);j--){
    19                 if(vis[j]!=vis[num[i]]) break;
    20                 las[i]=j;
    21             }
    22         }else{
    23             int flag=-1;
    24             for(int j=num[i];j>=max(num[i]-k+1,0);j--){
    25                 if(vis[j]==0) continue;
    26                 flag=j;las[i]=j;break;
    27             }
    28             if(flag==-1){
    29                 las[i]=max(num[i]-k+1,0);
    30                 for(int j=num[i];j>=max(num[i]-k+1,0);j--) vis[j]=i;
    31                 continue;
    32             }
    33             for(int j=las[i];j>=0;j--){
    34                 if(vis[j]==vis[las[i]]){flag=j;}
    35                 else break;
    36             }
    37             if((num[i]-flag+1)<=k){
    38                 las[i]=flag;
    39                 for(int j=flag;j<=num[i];j++) vis[j]=vis[flag];
    40                 continue;
    41             }else{
    42                 for(int j=las[i]+1;j<=num[i];j++) vis[j]=i;
    43                 las[i]=las[i]+1; continue;
    44             }
    45         }
    46     }
    47     for(int i=1;i<=n;i++){
    48         if(i==n) printf("%d
    ",las[i]);
    49         else printf("%d ",las[i]);
    50     }
    51     return 0;
    52 }
    View Code

    ________________________________________________________________________________________

    D题:Perfect Groups

    这个题目主要是题意难度,感觉读懂以后还是挺好做的

    主要是传递性的问题,要能保证接下来能传递下去,只要搞好了这一点就不难了。

    这个我们假设能分一组的是什么样的情况,就是假设 a*b是一个平方数,b*c是一个平方数。那么

    a*c也是一个平方数

    这个还是挺好证明的。就是a的奇数次的因子的位置和b的奇数次的因子的位置刚好对上,b的奇数次

    因子的个数和c的奇数次因子的个数刚好对上。。。。。。。。。。。。

    这样对上以后我们就可以我们利用传递性来做了

    这样预处理一下,确定a[j]最前面的那个可以和它组合的因子是那个。

    还有确定0的话可以放在任何一组,不要管他,0直接跳过即可。

    然后预处理一下,再枚举一下就ok了

    下面是代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cmath>
     6 #include <bitset>
     7 typedef long long ll;
     8 using namespace std;
     9 const int maxn=(int)(5e3+100);
    10 int n;
    11 ll num[maxn],pre[maxn],ans[maxn];
    12 int main(){
    13     scanf("%d",&n);
    14     for(int i=1;i<=n;i++) scanf("%lld",&num[i]);
    15     for(int i=1;i<=n;i++){
    16         if(num[i]==0) continue;
    17         for(int j=i-1;j>=1;j--){
    18             if(num[j]==0) continue;
    19             if((num[j]*num[i])<0) continue;
    20             ll d=num[j]*num[i];
    21             ll q=(ll)sqrt(d);
    22             if(d==(ll)(q*q)){
    23                 pre[i]=j;break;
    24             }
    25         }
    26     }
    27 
    28     for(int i=1;i<=n;i++){
    29         int snum=0;
    30         for(int j=i;j<=n;j++){
    31             if(pre[j]<i&&num[j]!=0) snum++;
    32             ans[max(snum,1)]++;
    33         }
    34     }
    35 
    36     for(int i=1;i<=n;i++){
    37         if(i==n) printf("%lld
    ",ans[i]);
    38         else printf("%lld ",ans[i]);
    39     }
    40     return 0;
    41 }
    View Code

    E题:The Number Games

    首先我们应该知道一点,就是有  2^(n+1)>2^n+2^(n-1)+....+2^1=2^(n+1)-2

    所以我们可以知道一点是我们应该是尽量保存大点,丢掉小的。

    所以有一种想法是直接按照度丢掉小的,但是这样是错误的。直接画个图就可知道。

    然后我觉得有一个肯定没有错的想法是保留大,即保留前n-k个大的。

    这个怎么保留呢,那么肯定一点是要以n为根把n留下来。

    接下来的想法是把n-1留下来,那么n-1这条链也要保存下来,那么n-1的这条链怎么保存呢????

    这个要验证,这个验证的话不能用暴力,得用倍增确定这个点要不要保存,就是往上面调一下就可以

    这个可以做到logn单步验证。

    下面是代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cmath>
     6 #include <bitset>
     7 #include <vector>
     8 #include <queue>
     9 typedef long long ll;
    10 using namespace std;
    11 const int maxn=(int)(1e6+100);
    12 int n,k;
    13 int ans[maxn];
    14 int tot=0;
    15 int in[maxn];
    16 vector<int> G[maxn];
    17 priority_queue<int> que;
    18 int main(){
    19     scanf("%d%d",&n,&k);
    20     for(int i=1;i<n;i++){
    21         int u,v;
    22         scanf("%d%d",&u,&v);
    23         in[u]++;in[v]++;
    24         G[u].push_back(v);
    25         G[v].push_back(u);
    26     }
    27     for(int i=1;i<=n;i++){
    28         if(in[i]==1) que.push(-i);
    29     }
    30 
    31     while(k){
    32         k--;
    33         int u=abs(que.top());
    34         ans[++tot]=abs(que.top());
    35         que.pop();
    36         for(int i=0;i<G[u].size();i++){
    37             int v=G[u][i];
    38             in[v]--;
    39             if(in[v]==1){
    40                 que.push(-v);
    41             }
    42         }
    43     }
    44 
    45     sort(ans+1,ans+tot+1);
    46     for(int i=1;i<=tot;i++){
    47         if(i==tot) printf("%d
    ",ans[tot]);
    48         else printf("%d ",ans[i]);
    49     }
    50     return 0;
    51 }
    View Code

    ——————————————————————————————————————

    这个该怎么来想呢?我们应该确定的一些事情是这个确实难搞

      2^(n+1)>2^n+2^(n-1)+....+2^1=2^(n+1)-2   (这个信息是重中之重)

     然后我们变成一点,保存大的,这个是肯定没错的(直接按度数丢掉小的是错误的,刚才证明了,

    这个其实有点难搞,因为需要证明)(以后最好就直接往直接正确上面的逻辑上面去想)

    保存大的之后,我们很好引入思维了,就是以n为根,接下来一个个贪心的保存,这个如果

    保存了i,i到根上面的数都要保存,这个也比较好搞,用个树上倍增即可,好搞的很

    ——————————————————————————————————————

  • 相关阅读:
    linux
    ansible
    语法糖
    jupyter login
    hadoop patch
    ganglia
    unixbench安装使用
    linux使用FIO测试磁盘的iops
    cpu事实负载使用top命令
    phoronix-test-suite测试云服务器
  • 原文地址:https://www.cnblogs.com/pandaking/p/12132355.html
Copyright © 2020-2023  润新知