您的位置:首页 > 其它

51nod 1406 与查询 [dp]

2018-01-09 18:56 363 查看

题面传送门

题解

一个数&x==x的条件可以理解为转换为二进制后,x为1的位要对应为1

设f[x]为范围内与&x==x的数的个数

若y转换为二进制后的所有1位x都有(y为x的子集),则对f[x]有贡献的数一定对f[y]有贡献

所以可以枚举子集转移,但是这样算会有重复,于是从高位向低位转移,想象一下把x​拆几个1掉就可以变成y​了

记得加输入输出优化

具体见代码

#include<cstdio>
#include<algorithm>
#define N 1000005
#define LL long long
using namespace std;

int n;
LL f
,pw[21];

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline int read(){
int a=0;char c=nc(),f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
while(c>='0'&&c<='9'){a=a*10+c-'0';c=nc();}
return a*f;
}

inline void print(LL x){if(x/10) print(x/10);putchar(x%10+'0');}

int main(){
n=read();
for(int i=1,x;i<=n;++i){
x=read();
++f[x];
}
pw[0]=1;
for(int i=1;i<=20;++i) pw[i]=pw[i-1]<<1;
for(int i=20;i>=0;--i)
for(int j=1;j<=1000000;++j)
if(j&pw[i])
f[j^pw[i]]+=f[j];
for(int i=0;i<=1000000;++i) print(f[i]),puts("\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: