51 nod 1406 与查询

1406 与查询

题目来源: CodeForces
基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
 

有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

 

/*
51 nod 1406 与查询

problem:
有n个整数。输出他之中和x相与之后结果为x的有多少个。x从0到1000000

solve:
如果x与a[i]相与之后为x,那么x必定是a[i]二进制中1的组合.
所以就成了快速求x中1的所有组合.

最开始是枚举x,然后从高位到低位枚举. cnt[i - (1 << j)] += cnt[i];
但是有的时候会出现重复,比如: 1011.
循环置换一下就好了

hhh-2016/09/09-16:19:21
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <stdio.h>
#include <cstring>
#include <vector>
#include <math.h>
#include <queue>
#include <set>
#include <map>
#define lson  i<<1
#define rson  i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define scanfi(a) scanf("%d",&a)
#define scanfs(a) scanf("%s",a)
#define scanfl(a) scanf("%I64d",&a)
#define scanfd(a) scanf("%lf",&a)
#define key_val ch[ch[root][1]][0]
#define eps 1e-7
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const ll mod = 1000000007;
const int maxn = 1001000;
const double PI = acos(-1.0);
const int limit = 33;


template<class T> void read(T&num)
{
    char CH;
    bool F=false;
    for(CH=getchar(); CH<'0'||CH>'9'; F= CH=='-',CH=getchar());
    for(num=0; CH>='0'&&CH<='9'; num=num*10+CH-'0',CH=getchar());
    F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p)
{
    if(!p)
    {
        puts("0");
        return;
    }
    while(p) stk[++ tp] = p%10, p/=10;
    while(tp) putchar(stk[tp--] + '0');
    putchar('\n');
}

int cnt[maxn];

int main()
{
    int n,Max,x;
    clr(cnt,0);
    read(n);
    Max = 0;
    for(int i = 1; i <=n; i++)
    {
        read(x),Max = max(x,Max);
        cnt[x] ++ ;
    }
    int begi = min(1000001,Max);
//    cnt[0] = n;
    for(int j = 20; j >= 0 ; j --)
    {
        for(int i = 1; i <= begi; i++)
        {
            if(i & (1 << j))
            {
                cnt[i - (1 << j)] += cnt[i];
            }
        }
    }
    cnt[0] = n;
    for(int i = 0;i <= 1000000;i ++)
        print(cnt[i]);
//    for(int i = 0; i <= 10; i ++)
//        print(cnt[i]);
    return 0;
}

  

posted @ 2016-09-09 16:40  Przz  阅读(784)  评论(0编辑  收藏  举报