zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    html5+css3中的background: -moz-linear-gradient 用法 (转载)
    CentOS 安装Apache服务
    Linux 笔记
    CURL 笔记
    Spring Application Context文件没有提示功能解决方法
    LeetCode 389. Find the Difference
    LeetCode 104. Maximum Depth of Binary Tree
    LeetCode 520. Detect Capital
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode 136. Single Number
  • 原文地址:https://www.cnblogs.com/shzr/p/10959719.html
Copyright © 2011-2022 走看看