51nod 1406 位运算/dp

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=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

枚举每个数的子集然后更新,但是...会出现重复更新的情况,例如 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 }
时间: 2024-10-13 20:49:28

51nod 1406 位运算/dp的相关文章

bzoj5108 [CodePlus2017]可做题 位运算dp+离散

[CodePlus2017]可做题 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 87  Solved: 63[Submit][Status][Discuss] Description qmqmqm希望给sublinekelzrip出一道可做题.于是他想到了这么一道题目:给一个长度为n的非负整数序列ai,你需 要计算其异或前缀和bi,满足条件b1=a1,bi=bi?1 xor ai(i≥2).但是由于数据生成器出现了问题,他生成的序列a 的长度特

51nod 1406 与查询 dp 考虑每一位 避免重复

题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1406 题意: 有n个整数.输出他之中和x相与之后结果为x的有多少个.x从0到1,000,000 思路: http://blog.csdn.net/bahuia/article/details/55653495 这题dp的思路很巧妙,分析一下题目,很容易想到,若已经求出一个数x的合法结果数,那么对于x位数上的子集来说,x的结果对他们也同样适用,例如,能和x=1

【CF908E】New Year and Entity Enumeration 位运算+DP

[CF908E]New Year and Entity Enumeration 题意:给定$M=2^m-1$,我们称一个集合S是好的,当且仅当它满足:1.$\forall a\in S,a \mathrm{xor} M \in S$,2.$\forall a,b\in S,a \mathrm{and} b \in S$,3.\forall a\in S,a\le M. 现在给定集合T,求有多少个好的集合S,满足T是S的子集. m<=1000,|T|<=50. 题解:显然有了与和取反以后,我们还

bzoj4300 绝世好题(位运算+DP)

为什么要写这道题呢?因为它是"绝世好题". 题意:给定n个数,在其中找出一段子序列b,使得b[i]&b[i-1]!=0,求出满足条件的最长子序列长度. 输入:第一行:一个整数n,表示数列的个数. 第二行:n个整数,表示数列a. 输出:一行,一个整数,表示最长的子序列长度. 输入样例: 3 1 2 3 输出样例: 2 解析:若b[i]&b[i-1]!=0,即b[i]与b[i-1]在二进制下有一位相同且都为1.那么设dp[i]表示前i个数所能达到的最长子序列长度,那么在转移

leetcode 201. Bitwise AND of Numbers Range(位运算,dp)

Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive. For example, given the range [5, 7], you should return 4. 题解:如果m==n,那么答案就是m. 如果m<n,那么二进制最右边一位在最后的结果中肯定是0,那么就可以转化成子问题: rangeBi

51Nod 1069 Nim游戏 (位运算)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1069 有N堆石子.A B两个人轮流拿,A先拿.每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜.假设A B都非常聪明,拿石子的过程中不会出现失误.给出N及每堆石子的数量,问最后谁能赢得比赛. 例如:3堆石子,每堆1颗.A拿1颗,B拿1颗,此时还剩1堆,所以A可以拿到最后1颗石子. Input 第1行:一个数N,表示有N堆石子.(

HDU 4949 Light(插头dp、位运算)

比赛的时候没看题,赛后看题觉得比赛看到应该可以敲的,敲了之后发现还真就会卡题.... 因为写完之后,无限TLE... 直到后来用位运算代替了我插头dp常用的decode.encode.shift三个函数以及改改HASH值才勉强过的...7703ms 题意:给一个N*M的01矩阵,每次可以选一个格子进行2种操作,①翻转邻居格子②翻转邻居格子和自己.输出最小的总操作数使得矩阵全为0. 显然每个格子有4种操作(一.不操作:二.①②:三.①:四.②). 一开始写的时候用2位表示一个插头,一位用于表示翻转

基于DP+位运算的RMQ算法

来源:http://blog.csdn.net/y990041769/article/details/38405063 RMQ算法,是一个快速求区间最值的离线算法,预处理时间复杂度O(n*log(n)),查询O(1),所以是一个很快速的算法,当然这个问题用线段树同样能够解决. 问题:给出n个数ai,让你快速查询某个区间的的最值. 算法分类:DP+位运算 算法分析:这个算法就是基于DP和位运算符,我们用dp[i ][j]表示从第 i 位开始,到第 i + 2^j -1 位的最大值或者最小值. 那么

状压dp中常用的位运算式子

原址:状压dp入门 为了更好的理解状压dp,首先介绍位运算相关的知识. 1.’&’符号,x&y,会将两个十进制数在二进制下进行与运算,然后返回其十进制下的值.例如3(11)&2(10)=2(10). 2.’|’符号,x|y,会将两个十进制数在二进制下进行或运算,然后返回其十进制下的值.例如3(11)|2(10)=3(11). 3.’^’符号,x^y,会将两个十进制数在二进制下进行异或运算,然后返回其十进制下的值.例如3(11)^2(10)=1(01). 4.’<<’符号