题解 P3220 【[HNOI2012]与非】
Salamander · · 题解
与非(
所以相当于是这
然后我们考虑一下位与位之间的限制。如果这
为什么这样是对的?其他没有互相限制的位置上就一定可以任意取
类似于线性基的思想,我们可以构造这样一种方案:通过一些运算把某一位上只留下一个
于是我们可以把
10000000
01000000
00101000
00010000
00000100
00000011
利用这样的东西,我们通过他们之间的或运算,就可以构造出原来
复杂度应该是
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define For(i,_beg,_end) for(int i=(_beg),i##end=(_end);i<=i##end;++i)
#define Rep(i,_beg,_end) for(int i=(_beg),i##end=(_end);i>=i##end;--i)
template<typename T>T Max(const T &x,const T &y){return x<y?y:x;}
template<typename T>T Min(const T &x,const T &y){return x<y?x:y;}
template<typename T>int chkmax(T &x,const T &y){return x<y?(x=y,1):0;}
template<typename T>int chkmin(T &x,const T &y){return x>y?(x=y,1):0;}
template<typename T>void read(T &x){
T f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(x=0;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
x*=f;
}
typedef long long LL;
const int maxn=1010;
int n,k,c[65],tmp[65];
LL a[maxn],L,R;
vector<int>pos[65];
LL Dfs(LL n,int x,bool lim){
if(x<0)return 1;
if(!lim){
int cnt=0;
memcpy(tmp,c,sizeof c);
Rep(i,x,0) if(tmp[i]==-1){
cnt++;
For(j,0,pos[i].size()-1) tmp[pos[i][j]]=1;
}
return 1LL<<cnt;
}
LL res=0;
if(c[x]==-1){
For(i,0,(n>>x)&1){
For(j,0,pos[x].size()-1) c[pos[x][j]]=i;
res+=Dfs(n,x-1,lim&(i==((n>>x)&1)));
}
For(j,0,pos[x].size()-1) c[pos[x][j]]=-1;
return res;
}
else{
if(c[x]&&lim&&!((n>>x)&1))return 0;
return Dfs(n,x-1,lim&(c[x]==((n>>x)&1)));
}
}
LL Solve(LL x){
memset(c,-1,sizeof c);
if(x<0)return 0;
return Dfs(x,k-1,(x>>k)?0:1);
}
int main(){
read(n);read(k);read(L);read(R);
For(i,1,n) read(a[i]);
Rep(i,k-1,1) Rep(j,i-1,0){
bool flag=true;
For(p,1,n) if(((a[p]>>i)&1)^((a[p]>>j)&1)){
flag=false;
break;
}
if(flag) pos[i].push_back(j);
}
printf("%lld\n",Solve(R)-Solve(L-1));
return 0;
}