• Codeforces Global Round 1


    $Codeforces$ $Global$ $Round$ $1$

       看到CF首页上有$global$ $round$ $3$的通知,虽然没时间打,但是做做之前的场次还是OK的。

      (已经在线下写好了,感觉弄上来再调格式挺麻烦的,完整版戳这里

      A.Parity:http://codeforces.com/contest/1110/problem/A

      题意概述:以 $b$ 进制给出一个数,求它在十进制下的奇偶性。

      比较水,没什么好说的,按位判断即可。然后我不是很明白这道题为什么在cf上的评分是1000.

      
     1 # include <cstdio>
     2 # include <iostream>
     3 # define R register int
     4 
     5 using namespace std;
     6 
     7 int b,k,x;
     8 int ans;
     9 
    10 int main()
    11 {
    12     scanf("%d%d",&b,&k);
    13     for (R i=1;i<k;++i)
    14     {
    15     scanf("%d",&x);
    16     if(b%2==0||x%2==0) continue;
    17     ans++;    
    18     }
    19     scanf("%d",&x);
    20     if(x%2) ans++;
    21     if(ans%2) puts("odd");
    22     else puts("even");
    23     return 0;  
    24 }
    Parity

      B.Tape:http://codeforces.com/contest/1110/problem/B

      题意概述:你有一条长度为 $m$ 的带子,但是 $n$ 处破掉了,所以要用另一条来补上,你可以从另一条带子上截取任意长度用来补充,但是最多只能截取 $k$ 段,求最小的总长度。$k<=n<=10^5,m<=10^9$

      如果不考虑只能截取 $k$ 段的限制,那么每个破处打一个补丁就可以了,现在的问题是怎么把 $n$ 个补丁转化成 $k$ 个。只要把两个漏洞之间的部分也打上补丁,那么补丁的段数就会减少一,所以只需要将相邻的补丁间的长度都算出来,从小往大里连,连到段数符合要求即可。

      
     1 # include <cstdio>
     2 # include <iostream>
     3 # include <queue>
     4 # define R register int
     5 # define ll long long
     6 
     7 using namespace std;
     8 
     9 const int maxn=100005;
    10 int n,m,k,b[maxn];
    11 ll ans;
    12 priority_queue <int,vector<int>,greater<int> > q;
    13 
    14 int main()
    15 {
    16     scanf("%d%d%d",&n,&m,&k);
    17     ans=n;
    18     for (R i=1;i<=n;++i)
    19     scanf("%d",&b[i]);
    20     for (R i=1;i<n;++i)
    21     q.push(b[i+1]-b[i]-1);
    22     for (R i=1;i<=n-k;++i)
    23     ans+=q.top(),q.pop();
    24     cout<<ans;
    25     return 0;
    26 }
    Tape

       C. Meaningless Operations:http://codeforces.com/contest/1110/problem/C

      题意概述:定义一个这样的函数:$f(a) = max_{0 < b < a}{gcd(a oplus b, a > & > b)}. $,给出 $q$ 个 $a$,请求出 $f(a)$,$q<=10^3,2<=a<=2^{25}-1$

      本题看起来奥妙重重,但是样例可以给我们一点提示。

      可以发现,如果一个数的二进制位不全是1,那么让b来将这些空补上是最好不多的了。这样,异或值就是11..1的形式,与的值就是0,最大公约数就是异或值。因为b不能超过a,所以这显然就是最好的方案了。

      如果一个数的二进制位全是1又怎么办呢?打表啊...当然也有一个正经做法:在这种情况下,可以认为$f(x)=gcd(a-b,b)$,所以可以取到x的最大真因子;

      
     1 # include <cstdio>
     2 # include <iostream>
     3 # include <map>
     4 # define R register int
     5 
     6 using namespace std;
     7 
     8 int x,q;
     9 map <int,int> m;
    10 int m2[100];
    11 
    12 int main()
    13 {
    14     scanf("%d",&q);
    15     m[1]=0; m[3]=1; m[7]=1; m[15]=5; m[31]=1; m[63]=21; m[127]=1; m[255]=85; m[511]=73; m[1023]=341;
    16     m[2047]=89; m[4095]=1365; m[8191]=1; m[16383]=5461; m[32767]=4681; m[65535]=21845;
    17     m[131071]=1; m[262143]=87381; m[524287]=1; m[1048575]=349525; m[2097151]=299593;
    18     m[4194303]=1398101; m[8388607]=178481; m[16777215]=5592405; m[33554431]=1082401;
    19     for (R i=2;i<=26;++i) m2[i]=(1<<i)-1;
    20     while(q--)
    21     {
    22         cin>>x;    
    23         if(m[x]) cout<<m[x]<<endl;
    24         else
    25         {
    26             int l=0;
    27             while(x!=0) { x/=2,l++; }
    28             cout<<m2[l]<<endl;
    29         }
    30     }
    31     return 0;
    32 }
    Meaningless Operations

      D.Jongmah:http://codeforces.com/contest/1110/problem/D

      题意概述:给出n块瓷砖,每块有一个介于 $[1,m]$ 的大小,要将它们做成一些“三倍”(我也不知道这题在说些啥),一个“三倍”可以是这样的形式[x-1,x,x+1],也可以是[x,x,x]。求出最多能做几个“三倍”。$n<=10^6,m<=10^6$

      有两种比较简单的贪心思路:先凑第一种,再凑第二种。或者反过来。

      可惜,这两种做法都不对,给两组反例吧:

      1 1 1 2 2 2 3 3 3,答案为3;

      1 1 2 2 2 2 3 3 3 3 3 3 4 4 4 4 5 5,答案为6;

      如果想要dp,可以这样设置状态:$dp[i][j][k]$ 表示当前dp到i这种瓷砖,上一种和再上一种各剩下多少张时最多的“三倍”数量。但是空间又开不下。

      正解是用贪心的思想优化dp状态。

      既然问题在于空间不够,而 $i$ 一维显然没有优化空间,所以我们希望减少 $j$,$k$ 两维的上界。可以发现凑三个 $[x-1,x,x+1]$ 不如转化为 $[x-1,x-1,x-1]$ , $[x,x,x]$ , $[x+1,x+1,x+1]$,同一种连号最多只需要凑两组。这样一来,每种瓷砖需要留下的块数也就少了很多,可以进行dp了。

      
     1 # include <cstdio>
     2 # include <iostream>
     3 # include <cstring>
     4 
     5 using namespace std;
     6 
     7 const int N=1000006;
     8 int n,m,x,ans;
     9 int t[N],dp[N][5][3];
    10 
    11 void giv (int x,int y,int z,int v)
    12 {
    13     if(y>=6) dp[x][y-3][z]=max(dp[x][y-3][z],v+1);
    14     dp[x][y%3][z%3]=max(dp[x][y%3][z%3],v+(y/3)+(z/3));
    15     dp[x][min(y,4)][z%3]=max(dp[x][min(y,4)][z%3],v+z/3);
    16     dp[x][y%3][min(z,2)]=max(dp[x][y%3][min(z,2)],v+y/3);
    17     dp[x][min(y,4)][min(z,2)]=max(dp[x][min(y,4)][min(z,2)],v);
    18 }
    19 
    20 int main()
    21 {
    22     scanf("%d%d",&n,&m);
    23     for (int i=1;i<=n;++i) scanf("%d",&x),t[x]++;
    24     memset(dp,-1,sizeof(dp)); dp[0][0][0]=0;
    25     for (int i=1;i<=m;++i)
    26         if(t[i]>6) x=(t[i]-6)/3,t[i]=t[i]-3*x,ans+=x;
    27     for (int i=1;i<=m;++i)
    28         for (int j=0;j<=4;++j)
    29             for (int k=0;k<=2;++k)
    30             {
    31                 if(dp[i-1][j][k]==-1) continue;
    32                 int a=dp[i-1][j][k];
    33                 if(t[i]>=2&&j>=2&&k>=2) giv(i,t[i]-2,j-2,a+2);
    34                 if(t[i]>=1&&j>=1&&k>=1) giv(i,t[i]-1,j-1,a+1);
    35                 giv(i,t[i],j,a);
    36             }
    37     int fans=0;
    38     for (int i=0;i<=4;++i)
    39         for (int j=0;j<=2;++j)
    40             fans=max(fans,dp[m][i][j]);
    41     printf("%d",fans+ans);
    42     return 0;
    43 }
    Jongmah

    ---shzr

  • 相关阅读:
    今日计划
    今日计划
    个人品质
    翻译 《Why Indy?》计划&进度表
    今日计划
    一粒老鼠屎
    开两本字典聊天的感觉
    ObjectiveC初学指南
    todo格式定义
    制作TortoiseSVN最新版本的中文DLL(转)
  • 原文地址:https://www.cnblogs.com/shzr/p/10959719.html
Copyright © 2020-2023  润新知