BZOJ2728: [HNOI2012]与非

容易推出能用nand和括号做出所有逻辑运算。那么可以尝试乱搞,利用线性基做任意次异或,再加上几次别的运算,就很有可能能得到所有本来能得到的数了。

#include<cstdio>
int n,m;
typedef long long ll;
ll l[60],j,s,t;
void up(ll&i,ll j){
	j^=i,i<j?0:i=j;
}
void ins(ll j){
	for(int i=m-1;~i;--i){
		up(j,l[i]);
		if(j>>i&1){
			for(int k=i-1;~k;--k)
				up(j,l[k]);
			for(int k=m-1;k>i;--k)
				up(l[k],j);
			l[i]=j;
			break;
		}
	}
}
ll val(ll j){
	ll s=0,t=0;
	for(int i=m-1;~i;--i)
		if(l[i]){
			s=s<<1|(t^l[i])<j;
			if(s&1)
				t^=l[i];
		}
	return s+!!j;
}
int main(){
	scanf("%d%d%lld%lld",&n,&m,&s,&t);
	while(n--){
		scanf("%lld",&j);
		for(int i=m-1;~i;--i)
			ins(j|l[i]);
	}
	printf("%lld\n",val(t+1)-val(s));
}
posted @ 2016-10-19 20:01  f321dd  阅读(158)  评论(0编辑  收藏  举报