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 }