Description
有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的有多少个数字。
Solution
一个很显然的性质是若a&b==a则对于a的二进制上的每一位1都在b上同为1,这个可以形象地理解为两个集合的交操作,若 A∩B=A 则 A⊂B
考虑怎么统计答案。设f[x]是第x行的答案。若a是b的一个子集,那么每一个f[b]都要统计到f[a]中。但是这样做是会发生重复的,解决的方法就是从高位到低位倒着枚举即可
这题似乎卡常要读入输出优化
题目的输出解释有点坑,第i行输出的是i-1的答案
Code
#include <stdio.h>
#include <string.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
#define N 1<<21|1
int f[N];
int read() {
int x=0; char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x;
}
void writeln(int x) {
int prt[10]={};
do {prt[++prt[0]]=x%10;} while (x/=10);
drp(i,prt[0],1) putchar(prt[i]+'0');
putchar('\n');
}
int main(void) {
int n=read();
rep(i,1,n) {
f[read()]++;
}
drp(i,20,0) {
rep(j,0,1000000) {
if ((1<<i)&j) {
f[j^(1<<i)]+=f[j];
}
}
}
rep(i,0,1000000) {
writeln(f[i]);
}
return 0;
}