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 }

 

posted @ 2017-10-02 20:09  ╰追憶似水年華ぃ╮  阅读(268)  评论(0编辑  收藏  举报