Bzoj2728 [HNOI2012]与非

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 753  Solved: 361

Description

Input

输入文件第一行是用空格隔开的四个正整数N,K,L和R,接下来的一行是N个非负整数A1,A2……AN,其含义如上所述。 100%的数据满足K≤60且N≤1000,0<=Ai<=2^k-1,0<=L<=R<=10^18

Output

仅包含一个整数,表示[L,R]内可以被计算出的数的个数

Sample Input

3 3 1 4
3 4 5

Sample Output

4

HINT

 

样例1中,(3 NAND 4) NADN (3 NAND 5) = 1,5 NAND 5 = 2,3和4直接可得。

 

Source

 

位运算 线性基 DP

一个数与非自己,结果等于非(Not)

Not(x Nand y) = x And y

not+and可以搞出所有逻辑运算。

可以据此从读入的数中找出所有线性基,然后由大到小使用线性基,进行数位DP。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define LL long long
 6 using namespace std;
 7 const int mxn=1010;
 8 LL read(){
 9     LL x=0,f=1;char ch=getchar();
10     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
11     while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();}
12     return x*f;
13 }
14 int n,k;
15 LL L,R;
16 LL a[mxn],b[mxn],p[mxn];
17 int cnt=0;
18 bool vis[mxn];
19 LL solve(LL x){//数位DP 
20     if(x==-1)return -1;
21     int i;
22     LL res=0,ans=0;
23     for(i=1;i<=cnt;i++)
24         if(res+p[i]<=x){
25             res+=p[i];
26             ans+=(1LL<<cnt-i);
27         }
28     return ans;
29 }
30 int main(){
31     int i,j;
32     n=read();k=read();L=read();R=read();
33     LL ed=(1LL<<k)-1;
34     for(i=1;i<=n;i++)a[i]=read();
35     LL now=0;
36     for(i=k-1;i>=0;i--){
37         if(!vis[i]){
38             now=ed;
39             for(j=1;j<=n;j++){
40                 if((a[j]>>i)&1)    now&=a[j];
41                 else now&=(~a[j]);
42             }
43             for(j=0;j<=i;j++)
44                 if((now>>j)&1)vis[j]=1;
45             p[++cnt]=now;
46         }
47     }
48     printf("%lld\n",solve(R)-solve(L-1));
49     return 0;
50 }
51     

 

posted @ 2017-02-01 19:38  SilverNebula  阅读(458)  评论(0编辑  收藏  举报
AmazingCounters.com