bzoj 2728: [HNOI2012]与非

又是一个神题23333

我也不知道大神们是怎么手玩出与非是可以表示所有逻辑运算的(据TA爷说,有个什么什么表表可以查(不会就查表)),(我只搞出自己与非自己,剩下的不知道)

然后开始了艰难的扒题解道路2333

在表示出所有操作之后,就要开始构造了。(如果你是大神,手玩与非的时候肯定能发现两个数的(二进制)某两位相同的话,那么无论这两个数怎么搞,这两位都相同。(这不是很显然吗?))推广到所有数,那么我们就可以发现,只要找出哪些位有哪些数相同不就好了?那么如何找呢?(强行构造,如果是1就保留,0就取非,强行构造成1),所以所有的数就变成了这一位是1的了,然后找出所有和都是1的位,那么我们叫这是一个团,所以我们的任务就是用相同的方法找出所有的团,最后用类似数位DP的东西,处理一下就好了。

 1 #include<bits/stdc++.h>
 2 #define N 100005
 3 #define LL long long
 4 #define inf 0x3f3f3f3f
 5 using namespace std;
 6 inline LL ra()
 7 {
 8     LL x=0,f=1; char ch=getchar();
 9     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
10     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
11     return x*f;
12 }
13 LL a[1005],best[65];
14 bool flag[65];
15 int K;
16 LL query(LL n)
17 {
18     if (n<0) return 0;
19     LL ans=0; int sum=0;
20     for (int j=K; j--; ) sum+=(bool)best[j];
21     for (int j=K; j--; )
22     {
23         if (best[j])
24         {
25             sum--;
26             if (best[j]<=n)
27             {
28                 n-=best[j];
29                 ans|=1LL<<sum;
30             }
31         }
32     }
33     return ans+1;
34 }
35 int main()
36 {
37     int n=ra(); K=ra();LL l=ra(),r=ra(); 
38     if (l>=1LL<<K){
39         puts("0");
40         return 0;
41     }
42     r=min(r,(1LL<<K)-1);
43     for (int i=n; i--;) a[i]=ra();
44     for (int j=K; j--;)
45     {
46         if (!flag[j])
47         {
48             best[j]=(1LL<<K)-1;
49             for (int i=n; i--;)
50                 if (a[i]>>j&1) best[j]&=a[i];
51                 else best[j]&=~a[i];
52             for (int k=j; ~k; k--)
53                 if (best[j]>>k&1) flag[k]=1;
54         }
55     }
56     cout<<query(r)-query(l-1)<<endl;
57     return 0;
58 }

 

posted @ 2017-02-20 07:42  ws_ccd  阅读(255)  评论(0编辑  收藏  举报