• HNOI2012与非


    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);
    }
    
  • 相关阅读:
    P3180 [HAOI2016]地图
    P2787 语文1(chin1)- 理理思维
    P2221 [HAOI2012]高速公路
    P4137 Rmq Problem / mex
    P3746 [六省联考2017]组合数问题
    P2461 [SDOI2008]递归数列
    P3715 [BJOI2017]魔法咒语
    P3195 [HNOI2008]玩具装箱TOY
    Linux下的strerror是否线程安全?
    bash/shell的字符串trim实现
  • 原文地址:https://www.cnblogs.com/aurora2004/p/13055506.html
Copyright © 2020-2023  润新知