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; }
相关文章推荐
- 51nod 1406 与查询 类背包dp
- 51nod 1406 与查询 DP
- 【51nod】1406 与查询 DP
- 51nod 1406 与查询 二进制+暴力
- 51nod 1406:与查询
- 51nod-1406 与查询
- 51nod 1406 与查询
- 51nod 1406 与查询
- 51Nod-1406-与查询
- [矩阵快速幂 优化DP] 51Nod 1311 转换机
- HDU 3016 Man Down(线段树区间单点查询+DP)
- 51nod 1183 编辑距离(二维dp)
- 51NOD 1705 七星剑 [DP 期望的线性性质]
- 51nod 1294 修改数组(dp,逆向思维,最大上升子序列)
- [背包DP][小技巧] LOJ#6089. 小 Y 的背包计数问题 && 51NOD 1597 有限背包计数问题
- 51nod 1371 DP
- 51nod 1083 矩阵取数问题 ( dp
- 51nod 1412 AVL树的种类(DP)
- 【51nod】1022 石子归并V2 区间DP
- 51nod 1134 最长递增子序列(dp)