• Codeforces Round #279 (Div. 2)


    A. Team Olympiad

    水题英文还这么长。。。

     1 #include<bits/stdc++.h>
     2 #define eps 1e-9
     3 #define FOR(i,j,k) for(int i=j;i<=k;i++)
     4 using namespace std;
     5 typedef long long LL;
     6 int i,j,k,n,m,x,y,T,ans,big,cas;
     7 bool flag;
     8 vector <int> a[5];
     9 int num,t;
    10 int main()
    11 {
    12     scanf("%d",&n);
    13     for (i=1;i<=n;i++)
    14     {
    15         scanf("%d",&t);
    16         a[t].push_back(i);
    17     }
    18     num=min((int)a[1].size(),(int)a[2].size());
    19     num=min(num,(int)a[3].size());
    20     printf("%d
    ",num);
    21     for (i=0;i<num;i++)
    22     {
    23         printf("%d %d %d
    ",a[1][i],a[2][i],a[3][i]);
    24     }
    25     return 0;
    26 }
    View Code

    B. Queue

    有n个人排队,每个人都有一个编号,现给出每个人前边一人的编号和后边一人的编号(如果没有人则是0),求出原来队中人的顺序(输出编号)。

    模拟,因为编号只有10^6,因此可以开两个10^6的数组,a[i][0]记录编号为i的人前边的前边的人的编号,a[i][1]记录编号为i的人后边的后边的人的编号。

    显然从0开始能够确定偶数位置人的顺序,然后将他们标记为-1,再根据剩下的确定奇数位置的人的顺序即可。

     1 #include<bits/stdc++.h>
     2 #define eps 1e-9
     3 #define FOR(i,j,k) for(int i=j;i<=k;i++)
     4 using namespace std;
     5 typedef long long LL;
     6 int i,j,k,n,m,x,y,T,big,cas,a[1000006][2],st,l[200005],r[200005],ans[200005],temp;
     7 bool flag;
     8 int main()
     9 {
    10     scanf("%d",&n);
    11     for (i=1;i<=n;i++)
    12     {
    13         scanf("%d%d",&l[i],&r[i]);
    14         a[r[i]][0]=l[i];
    15         a[l[i]][1]=r[i];
    16     }
    17     for (st=a[0][1],j=2;st!=0;j+=2)//确定偶数位置人 
    18     {
    19         ans[j]=st;
    20         temp=a[st][1];
    21         a[st][0]=-1;//已经确定位置的人标记为-1 
    22         a[st][1]=-1;
    23         st=temp;
    24     }
    25     for (i=1;i<=n;i++) 
    26         if (a[l[i]][0]==0) 
    27         {
    28             st=l[i];//找到奇数位置最前边的人 
    29             break;
    30         }
    31     ans[1]=st;    
    32     j=1;
    33     for (;st!=0;st=a[st][1],j+=2)//确定奇数位置的人 
    34     {
    35         ans[j]=st;
    36     }
    37     for (i=1;i<n;i++) printf("%d ",ans[i]);
    38     printf("%d
    ",ans[n]);
    39     return 0;
    40 }
    View Code

    C. Hacking Cypher

    给一个大数(长度10^6)问能够否分割成两个数,前边的能被a整除,后边的能被b整除,所有数不能有前导零。

    模拟,取模的几个性质应该都懂吧,设某个数是def,那么def=d*100+e*10+f ,def mod n = ((d mod n)*(100 mod n)+(e mod n)*(10 mod n)+f mod n) mod n

    设pre[i]为前i位能否整除a,suf[j]为后j为能否整除b。先预处理出pre和suf,显然pre[i]=true 并且 suf[i+1]=true的时候就是答案。

    求suf的时候就可以通过前一位的pre值判断是否有解了,因此代码中没有开suf数组。

     1 #include<bits/stdc++.h>
     2 #define eps 1e-9
     3 #define FOR(i,j,k) for(int i=j;i<=k;i++)
     4 using namespace std;
     5 typedef long long LL;
     6 int i,j,k,n,m,x,y,T,ans,big,cas,a,b,len,w;
     7 bool flag,pre[1000005];
     8 char s[1000005];
     9 int main()
    10 {
    11     scanf("%s",s);
    12     scanf("%d%d",&a,&b);
    13     len=strlen(s);
    14     for (i=0;i<len-1;i++)
    15     {
    16         x=(x*10+s[i]-'0')%a;
    17         if (x==0)
    18         {
    19             pre[i]=true;
    20         }
    21     }
    22     w=1;x=0;
    23     for (i=len-1;i>0;i--)
    24     {
    25         x=(x+w*(s[i]-'0'))%b;
    26         w=w*10%b;
    27         if (x==0&&pre[i-1]&&s[i]!='0')
    28         {
    29             printf("YES
    ");
    30             for (j=0;j<i;j++)
    31             {
    32                 printf("%c",s[j]);
    33             }
    34             printf("
    ");
    35             for (j=i;j<len;j++)
    36             {
    37                 printf("%c",s[j]);
    38             }
    39             printf("
    ");
    40             return 0;
    41         }
    42     }
    43     
    44     printf("NO
    ");
    45     return 0;
    46 }
    View Code

    D. Chocolate

    给两个巧克力,尺寸分别为a1*b1,a2*b2,现在想让它们的面积相同,有两种措施:

    1.吃掉其中一个巧克力的一半

    2.吃掉其中一个巧克力的1/3

    并且剩下每次操作后剩余巧克力尺寸是整数,问至少操作几次。。。并输出最终巧克力的尺寸

    先让a1,a2,b1,b2分别不断整除2再不断整除3,直到不能整除为止,如果最终的a1*b1不等于a2*b2,则说明无解,输出-1

    (假设存在有解a1,b1,a2,b2,则由题目一定有a1*b1=a2*b2,a1*b1,a2*b2一定有相同的2的因子数和3的因子数,这时让它们不断整除2整除3,直到不能整除为止,a1*b1=a2*b2仍然成立)

    设s1=a1*b1,s2=a2*b2,则如果s1/gcd(s1,s2)不等于s2/gcd(s1,s2),说明无解。

    有解的时候s1'=s2',一定有s1'/gcd(s1',s2')=s2'/gcd(s1',s2')=s1/gcd(s1,s2)=s2/gcd(s1,s2)

    下面就是解这个式子:

    s1*(1/2)x1*(2/3)y1 =s2*(1/2)x2*(2/3)y2 可以化简为

    s1 =s2 * 2x1-x2-y1+y2 * 3y1-y2
    找s1与s2关于2和3的因子数之差就能算出答案。

     1 #include<bits/stdc++.h>
     2 #define eps 1e-9
     3 #define FOR(i,j,k) for(int i=j;i<=k;i++)
     4 using namespace std;
     5 typedef long long LL;
     6 LL i,j,k,n,m,x,y,T,ans,big,cas,a[5],b[5],c[5],d[5],t,thr,two;
     7 bool flag;
     8 int main()
     9 {
    10     for (i=1;i<=4;i++) scanf("%I64d",&a[i]);
    11     for (i=1;i<=4;i++)
    12     {
    13         t=a[i];
    14         while (t%2==0)
    15         {
    16             t/=2;
    17             b[i]++;//记录因子2的个数 
    18         }
    19         while (t%3==0)
    20         {
    21             t/=3;
    22             c[i]++;//记录因子3的个数 
    23         }
    24         d[i]=t;
    25     }
    26     if (d[1]*d[2]!=d[3]*d[4]) 
    27     {
    28         printf("-1
    ");
    29         return 0;
    30     }
    31     thr=c[3]+c[4]-c[1]-c[2];
    32     if (thr>0)
    33     {
    34         t=thr;
    35         while (t>0&&a[3]%3==0)
    36         {
    37             a[3]=a[3]*2/3;
    38             t--;
    39         }
    40         while (t>0&&a[4]%3==0)
    41         {
    42             a[4]=a[4]*2/3;
    43             t--;
    44         }
    45     } else
    46     {
    47         t=-thr;
    48         while (t>0&&a[1]%3==0)
    49         {
    50             a[1]=a[1]*2/3;
    51             t--;
    52         }
    53         while (t>0&&a[2]%3==0)
    54         {
    55             a[2]=a[2]*2/3;
    56             t--;
    57         }
    58     }
    59     two=b[3]+b[4]-b[1]-b[2]+thr;//记得加上因除去因子3而多出来的因子2 
    60     
    61     if (two>0)
    62     {
    63         t=two;
    64         while (t>0&&a[3]%2==0)
    65         {
    66             a[3]=a[3]/2;
    67             t--;
    68         }
    69         while (t>0&&a[4]%2==0)
    70         {
    71             a[4]=a[4]/2;
    72             t--;
    73         }
    74     } else
    75     {
    76         t=-two;
    77         while (t>0&&a[1]%2==0)
    78         {
    79             a[1]=a[1]/2;
    80             t--;
    81         }
    82         while (t>0&&a[2]%2==0)
    83         {
    84             a[2]=a[2]/2;
    85             t--;
    86         }
    87     }
    88     printf("%I64d
    ",abs(thr)+abs(two));
    89      printf("%I64d %I64d
    %I64d %I64d
    ",a[1],a[2],a[3],a[4]);
    90     return 0;
    91 }
    View Code

    E. Restoring Increasing Sequence

    给出严格递增的几个数,其中几个数的某几位不知道用符号?给出,输出一种方案。

    分类讨论,这类题目写的好烦=。=#

    首先讨论与上一位的长度(第一个数的上一位设为0)的关系,如果他们的长度相等再从头到尾递归扫描。

    用dfs(i)=0表示到第i位是否需要向前边借位,比如数据:

    pre=14349

    now=14?4?

    now的第5位的问号处只能是0,这时如果要满足题意,就一定要求now的前边4位组成的数 比 pre的前四位组成的数大,因此dfs(5)=1。

    如果到递归第一个问号后仍然需要借位,则说明无解,比如:

    pre=14949

    now=14?49

    第一个问号处dfs(3)=1,而前边两位的数不可能比pre的前两位大,因此输出NO。

    其它的讨论细节乱搞一下,再乱搞乱搞。。。。还是详见代码吧:

      1 #include<bits/stdc++.h>
      2 #define eps 1e-9
      3 #define FOR(i,j,k) for(int i=j;i<=k;i++)
      4 using namespace std;
      5 typedef long long LL;
      6 int i,j,k,n,m,x,y,T,big,cas,last_len,len;
      7 bool flag;
      8 char last[10],s[10],bf[10],ans[100005][10];
      9 bool dfs(int x)//false为不需要进位,true表示需要进位 
     10 {
     11     if (x>=len) return 1; 
     12     if (s[x]=='?')
     13     {
     14         if (dfs(x+1))
     15         {
     16             s[x]=last[x];
     17             if (last[x]=='9')
     18             {
     19                 s[x]='0';
     20                 return 1;
     21             }else
     22             {
     23                 s[x]=last[x]+1;
     24                 return 0;
     25             }
     26         }else
     27         {
     28             s[x]=last[x];
     29             return 0;
     30         }
     31     }else
     32     {
     33         if (s[x]>last[x])
     34         {
     35             for (int i=x+1;i<len;i++)
     36             {
     37                 if (bf[i]=='?') s[i]='0';
     38             }
     39             return 0;
     40         }else
     41         if (s[x]<last[x])
     42         {
     43             for (int i=x+1;i<len;i++)
     44             {
     45                 if (bf[i]=='?') s[i]='0';
     46             }
     47             return 1;
     48         }else
     49         {
     50             return dfs(x+1);
     51         }
     52     }
     53 }
     54             
     55 
     56 int main()
     57 {
     58     scanf("%d",&n);
     59     strcpy(last,"0"); last_len=0;
     60     for (i=1;i<=n;i++)
     61     {
     62         scanf("%s",s);
     63         len=strlen(s);
     64         if (last_len>len)
     65         {
     66             printf("NO
    ");
     67             return 0;
     68         }else
     69         if (last_len<len)
     70         {
     71             if (s[0]=='?') s[0]='1';
     72             for (j=1;j<len;j++)
     73             {
     74                 if (s[j]=='?')
     75                 {
     76                     s[j]='0';
     77                 }
     78             }
     79             strcpy(ans[i],s);
     80             last_len=len;
     81             strcpy(last,s);
     82         }else
     83         {
     84             strcpy(bf,s);
     85             if (dfs(0))
     86             {
     87                 printf("NO
    ");
     88                 return 0;
     89             }else
     90             {
     91                 strcpy(ans[i],s);
     92                 last_len=len;
     93                 strcpy(last,s);
     94             }
     95         }
     96     }
     97     printf("YES
    ");
     98     for (i=1;i<=n;i++)
     99     {
    100         printf("%s
    ",ans[i]);
    101     }
    102     return 0;
    103 }
    View Code

    F. Treeland Tour

    给一棵最多6000个结点的树,每个点有权值,求其中的一条链,使得LIS的序列和最大。

    网上有人竟然枚举起点+求LIS o(N^2logN) 通过了,醉了,看来数据是很水了,在board上点开看了几个人的代码也是这样写的,不知道正解是怎样


    啊,第一场做出5道题的CF比赛,第一次排名这么靠前,只是不算rating。。。截个图

  • 相关阅读:
    每天学习Linux之-系统启动过程
    差模和共模干扰
    每天学习Linux之-目录结构
    欧姆龙CP1H 原点搜索和原点返回功能
    NPN,PNP接线总结
    MyBatis插件开发
    MyBatis运行原理
    MyBatis逆向工程
    MyBatis-Spring整合
    MyBatis缓存机制
  • 原文地址:https://www.cnblogs.com/zhyfzy/p/4117481.html
Copyright © 2020-2023  润新知