51nod 1406 与查询




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&#x2229;B=A” role=”presentation” style=”position: relative;”>AB=AA∩B=A

考虑怎么统计答案。设f[x]是第x行的答案。若a是b的一个子集,那么每一个f[b]都要统计到f[a]中。但是这样做是会发生重复的,解决的方法就是从高位到低位倒着枚举即可

这题似乎卡常要读入输出优化
题目的输出解释有点坑,第i行输出的是i-1的答案

Code


#include<bits/stdc++.h>
using namespace std;
const int N=1000001;
int f[N],i,j,n;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x=0,fl=1;char ch=gc();
    for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
    for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
    return x*fl;
}
inline void wri(int a){if(a<0)a=-a,putchar('-');if(a>=10)wri(a/10);putchar(a%10|48);}
inline void wln(int a){wri(a);puts("");}
int main(){
    n=read();
    for (i=0;i<n;i++) f[read()]++;
    for (j=0;j<20;j++)
        for (i=N-1;i;i--)
            if (i&(1<<j)) f[i^(1<<j)]+=f[i];
    for (i=0;i<N;i++) wln(f[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值