• Atcoder Tenka1 Programmer Contest D: IntegerotS 【思维题,位运算】


    http://tenka1-2017.contest.atcoder.jp/tasks/tenka1_2017_d

    给定N,K和A1...AN,B1...BN,选取若干个Ai使它们的或运算值小于等于K时,使得对应的ΣBi值最大,求最大值。

    其实我不大理解为什么要这么弄。

    一个数K,如果X小于它,那么K的二进制中第r位是1,X的第r位可以是0或1;但如果K的第r位是0,X的第r位一定是0。

    我只能勉强这样想:

      可以先选定一个或运算值的上限tmp,如果(Ai|tmp==tmp),那么根据或运算性质当前这个Ai是肯等可以选的,由于Bi>0,自然能选的越多越好。但是要是一个一个枚举或运算上限显然不现实。所以要按照K的二进制来枚举,把K中位是1的变为0,前面位不变,后面位全变为1。

    codeforce上有人这么写:

    Let's constder about the pattern of K = 13:
    All of buying things are 0 (0 or 1) (0 or 1) (0 or 1) in binary-representation, 0 — 7 in decimal
    All of buying things are 1 0 (0 or 1) (0 or 1) in binary-representation, 8 — 11 in decimal
    All of buying things are 1 1 0 (0 or 1) in binary-representation, 12 — 13 in decimal
    You can choose any pattern to buying, of above patterns.

    Let's constder about an another pattern, K = 22:
    All of buying things are 0 (0 or 1) (0 or 1) (0 or 1) (0 or 1) in binary-representation, 0 — 15 in decimal
    All of buying things are 1 0 0 (0 or 1) (0 or 1) in binary-representation, 16 — 19 in decimal
    All of buying things are 1 1 0 0 (0 or 1) in binary-representation, 20 — 21 in decimal
    All of buying things are 1 1 0 0 0 in binary-representation, 22 in decimal
    You can choose any pattern to buying, of above patterns.

    So, you can divide [1, K] into logK parts (maximum). The complexity is N * logK = O(NlogK).

    官方题解:

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 typedef long long ll;
     5 const int maxn=1e5+100;
     6 int a[maxn],b[maxn];
     7 int fac[32];
     8 
     9 int main()
    10 {
    11     int N,K;
    12     scanf("%d%d",&N,&K);
    13     ll res=0;
    14     for(int i=0;i<N;i++){
    15         scanf("%d%d",&a[i],&b[i]);
    16         if((a[i]|K)==K) res+=b[i];
    17     }
    18     for(int i=0;i<=30;i++)
    19         fac[i]=1<<i;
    20     for(int i=1;i<=30;i++){
    21         if(K&fac[i]){
    22             ll cnt=0;
    23             int tmp=(K^fac[i])|(fac[i]-1);//把当前位置为0,前面位不变,后面位全为1
    24             for(int j=0;j<N;j++)
    25                 if((a[j]|tmp)==tmp) cnt+=b[j];
    26             res=max(res,cnt);
    27         }
    28     }
    29     cout<<res<<endl;
    30 }
  • 相关阅读:
    编程爱好者论坛第六次编程比赛题目
    google china code jam round2 div1 1000分题
    ogl2dlibsdl cvs repository @ cosoft
    偶尔也提一个游戏点子:宇宙碰撞
    今天看到一些笑话...
    google china code jam入围赛的一个题
    用Regular expression寻找源代码中的汉字字符串
    生成函数理论初步
    Komodo 的中文支持
    “豪华版”的USB延长线
  • 原文地址:https://www.cnblogs.com/zxhyxiao/p/7622206.html
Copyright © 2020-2023  润新知