首页 > 其他 > 详细

HNOI2012与非

时间:2020-06-06 18:30:30      阅读:32      评论:0      收藏:0      [点我收藏+]

HNOI2012与非

技术分享图片

技术分享图片

发现用与非可以实现一切操作

\[not A=AnandA \]

\[AorB=not((notA)nand(notB)) \]

\[AandB=not(AnandB) \]

\[AxorB=not(((notA)and(notB))or(AandB)) \]

发现若n个数的某两位相等,那么无论怎么操作,最后都相等,其余没限制的可以随意填0/1

证明可以用线性基思想,我们总能构造出只有这些相等位为1,剩下的为0的数来,然后随意选几个数异或成为最后的答案(把这一为为0的数取反,然后把所有数异或到一起)

然后数位DP即可

//starusc
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c==‘-‘)f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
int pos[64],b[64];
int dp(int n,int p,int fl){
	if(p==-1)return 1;
	int ret=0;
	if(!fl){
		for(int i=0;i<=p;i++)
			if(!pos[i])ret++;
		return 1ll<<ret;
	}
	int mx=(n>>p)&1;
	if(pos[p]){
		if(b[pos[p]]<=mx)return dp(n,p-1,b[pos[p]]==mx);
		return 0;
	}
	for(int i=0;i<=mx;i++){
		b[p]=i;
		ret+=dp(n,p-1,i==mx);
	}
	return ret;
}
int k;
inline int solve(int n){
	if(n==-1)return 0;
	return dp(n,k-1,(n>>k)?0:1);//
} 
int n,L,R,a[1004];
signed main(){
	n=read();k=read();L=read();R=read();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int u=0,fl;u<k;u++)
		for(int v=k-1;v>u;v--){
			fl=1;
			for(int i=1;i<=n;i++)
				if(((a[i]>>u)&1)^((a[i]>>v)&1)){fl=0;break;}//
			if(fl){pos[u]=v;break;}
		}
	cout<<solve(R)-solve(L-1);
	return (0-0);
}

HNOI2012与非

原文:https://www.cnblogs.com/aurora2004/p/13055506.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!