ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[HNOI2012]与非

2022-01-05 14:58:36  阅读:285  来源: 互联网

标签:const int nand long HNOI2012 read 与非 define


与非

题解

显然,我们的 n a n d nand nand是一种按位运算操作,我们发现我们可以通过 n a n d nand nand来还原其他的基础位运算操作。
n o t   A = A   n a n d   A A   o r   B = ( n o t   A )   n a n d   ( n o t   B ) A   a n d   B = n o t   ( A   n a n d   B ) A   x o r   B = ( n o t   ( A   a n d   B ) )   a n d   ( A   o r   B ) not\,A=A\,nand\,A\\A\,or\,B=(not\,A)\,nand\,(not\,B)\\A\,and\,B=not\,(A\,nand\,B)\\A\,xor\,B=(not\,(A\,and\,B))\,and\,(A\,or\,B) notA=AnandAAorB=(notA)nand(notB)AandB=not(AnandB)AxorB=(not(AandB))and(AorB)所以所有的能够让 a a a通过基础按位运算得到的数都可以通过 n a n d nand nand得到。
而 A   n a n d   B A\,nand\,B AnandB自身可以翻译做 n o t   ( A   a n d   B ) not\,(A\,and\,B) not(AandB),所以通过基础按位运算得不到的数,都不可能通过 n a n d nand nand操作得到。
所以我们只需要看看我们通过基础按位运算得到哪些数就可以了。

显然,这样的话我们很容易联想到线性基的形式,可以去尝试求出我们 a a a的基底。
由于我们可以采用所有的位运算,所以,如果任意两位的 1 1 1在所有的 a a a中出现情况一致,那么它们就必然属于同一个基。
于是,我们就能够 O ( n k ) O\left(nk\right) O(nk)地轻松求出所有的基底。
然后就可以用类似数位 d p dp dp的方法来统计答案了,其实也就是直接贪心。

时间复杂度 O ( n k ) O\left(nk\right) O(nk)。

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 2005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL; 
typedef long double ld;
typedef pair<int,int> pii;
const LL INF=0x3f3f3f3f3f3f;    
const int mo=1e9+9;
const int inv2=5e8+4;
const int jzm=233333333;
const int zero=100;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1)t=1ll*t*a%p;a=1ll*a*a%p;s>>=1;}return t;}
int n,K,tot,c[65];
LL L,R,a[MAXN],b[65],lim;
bool vis[65];
LL sakura(LL up){
	if(up<0)return 0;LL now=0,res=0;
	for(int i=K-1;i>=0;i--)
		if(!vis[i]&&now+b[i]<=up)
			now+=b[i],res+=(1LL<<c[i]-1);
	return res+1LL;
}
signed main(){
	read(n);read(K);read(L);read(R);lim=(1LL<<K)-1LL; 
	for(int i=1;i<=n;i++)read(a[i]);
	for(int i=K-1;i>=0;i--){
		if(vis[i])continue;b[i]=lim;
		for(int j=1;j<=n;j++)
			if(a[j]&(1LL<<i))b[i]&=a[j]; 
			else b[i]&=lim^a[j];
		for(int j=0;j<i;j++)if(b[i]&(1LL<<j))vis[j]=1;
	}
	c[0]=!vis[0];for(int i=1;i<K;i++)c[i]=c[i-1]+(!vis[i]);
	printf("%lld\n",sakura(R)-sakura(L-1LL));
	return 0;  
}

谢谢!!!

标签:const,int,nand,long,HNOI2012,read,与非,define
来源: https://blog.csdn.net/Tan_tan_tann/article/details/122323090

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有