zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    MillerRabin
    BM算法总结
    高斯消元处理自由变元的方法
    [IOI2019]矩形区域
    费用流处理负圈的方法
    回文自动机(PAM)总结
    [TJOI2017]龙舟
    luogu P2252 [SHOI2002]取石子游戏|【模板】威佐夫博弈
    博弈论
    构造
  • 原文地址:https://www.cnblogs.com/zxhyxiao/p/7622206.html
Copyright © 2011-2022 走看看