51nod 1406 位运算/dp
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1406
题目来源: CodeForces
基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
![](http://file.51nod.com/images/icon/star.png)
![](http://file.51nod.com/images/icon/plus.png)
有n个整数。输出他之中和x相与之后结果为x的有多少个。x从0到1,000,000
Input
第一行输入一个整数n。(1<=n<=1,000,000). 第二行有n个整数a[0],a[1],a[2],...a[n-1],以空格分开.(0<=a[i]<=1,000,000)
Output
对于每一组数据,输出1000001行,第i行对应和i相与结果是i的有多少个数字。
Input示例
3 2 3 3
Output示例
3 2 3 2 0 0 …… 后面还有很多0
枚举每个数的子集然后更新,但是...会出现重复更新的情况,例如 1101->(1100,1001,101), 这些数有些子集重复导致WA。
其实只要把两次循环交换一下就避免了这种情况!
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define inf 0x3f3f3f3f 5 LL mod=1e9+7; 6 int dp[1000005]; 7 inline int read() 8 { 9 char c; while(!isdigit(c=getchar())); 10 int r=c-'0'; while(isdigit(c=getchar())) {r=(r<<3)+(r<<1)+c-'0';} 11 return r; 12 } 13 char _n='\n'; 14 inline void write(int x) 15 { 16 int a1=0,a[20]; 17 a[1]=0; 18 if (!x) a1++; 19 while (x) 20 { 21 a[++a1]=x%10;x/=10; 22 } 23 for (int i=a1;i>=1;i--) 24 putchar(a[i]+'0'); 25 putchar(_n); 26 } 27 int main() 28 { 29 int N,i,j,k,ai; 30 scanf("%d",&N); 31 for(i=1;i<=N;++i){ 32 dp[read()]++; 33 } 34 for(j=20;j>=0;--j){ 35 for(i=1;i<=1000000;++i) 36 { 37 if(i&(1<<j)) dp[i^(1<<j)]+=dp[i]; 38 } 39 } 40 cout<<N<<endl; 41 for(i=1;i<=1000000;++i) {write(dp[i]);} 42 return 0; 43 }