51nod1406 与查询 dp

55 篇文章 0 订阅
21 篇文章 0 订阅

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,这个可以形象地理解为两个集合的交操作,若 AB=A AB

考虑怎么统计答案。设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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值