HDU 4810 Wall Painting【二进制+异或+暴力枚举】

给出n个数

求从这n个数取k个数异或,所有情况得到的值(Cnk个值(可能有些相同))全加起来的值是多少

k从1到n

输出这n个数

这题一开始想毫无思绪

也没有说这n个数的大概范围,想用背包来着本来

结果发现它是这么解的

就样例来说,把四个数1,2,10,1拆开,当前是取k个数

0001

0010

1010

0001

对第四位来说,如果某些方案是取k个数异或后为0,那么等于 0*方案数,这个我们可以不用管它

如果某些方案是取2个数异或后为1,那么等于1*方案数

可以看到第四位有1个1,那么异或为1的方案数就是C31*C11,同理,第二位有2个1,那么就是C21*C21

答案也就是

(1<<3)*C31*C11 + (1<<1)C21*C21 +(1<<0)C21*C21

事先打好C1000 1000的表即可

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int C[1111][1111];
const int MOD=1e6+3;
#define LL long long
int main(){
#ifndef ONLINE_JUDGE
        freopen("G:/in.txt","r",stdin);
        //freopen("G:/myout.txt","w",stdout);
#endif
	int N;
	C[0][0]=1;
	for(int i=1;i<=1000;i++){
		for(int j=0;j<=i;j++){
			if(j==0) C[j][i]=1;
			else C[j][i]=(C[j][i-1]+C[j-1][i-1])%MOD;
		}

	}
	while(scanf("%d",&N)!=EOF){
		int tmp;
		int num[31];
		memset(num,0,sizeof(num));
		for(int i=1;i<=N;i++){
			scanf("%d",&tmp);
			for(int i=0;i<=30;i++)
				if((tmp>>i)&1)
					num[i]++;
		}
		int ans[1111];
		memset(ans,0,sizeof(ans));
		for(int i=1;i<=N;i++)
			for(int j=0;j<=30;j++)
				for(int k=1;k<=num[j] && k<=i;k+=2){
					ans[i]=(ans[i]+(LL)(1<<j)%MOD*(LL)C[k][num[j]]%MOD*(LL)C[i-k][N-num[j]]%MOD)%MOD;
				}
		for(int i=1;i<=N;i++)
			printf("%d%c",ans[i],i==N?'\n':' ');
	}
	return 0;
}
时间: 2024-11-08 19:34:49

HDU 4810 Wall Painting【二进制+异或+暴力枚举】的相关文章

HDU 4810 Wall Painting (位操作-异或)

OJ题目:click here~~ 题目分析:给n个数.从这n个数中选择i个数,共同拥有c(n , i)种情况.将每种情况中的i个数异或,将这c(n , i)个异或结果求和,就得到第i个输出结果,i属于[1  n]. 求x个数的异或,等于分别对x个数的同一二进制位进行异或,然后加权求和. 于是将n个数表示成二进制的形式.对于本题,32位就够. 由于,奇数个1的异或 = 1 , 偶数个1的异或 = 0 . 统计每位上1的个数 .然后对于第j个二进制位.枚举所选中的1的个数.加权求和,就可以得结果.

hdu 4810 Wall Painting (组合数学+二进制)

题目链接 下午比赛的时候没有想出来,其实就是int型的数分为30个位,然后按照位来排列枚举. 题意:求n个数里面,取i个数异或的所有组合的和,i取1~n 分析: 将n个数拆成30位2进制,由于每个二进制位异或后相加和原来的数异或相加是一样的,所以只需要对每一位累加计算,用组合数学取数就行了,奇数个异或得1,偶数个异或得0,再乘以自己的二进制位值,复杂度O(30*n*n) 1 #include <iostream> 2 #include <cstdio> 3 #include <

HDU 4810 Wall Painting(异或 +按位容斥)

直接不会,预估时间复杂度,对于C(n,m) 到规模为500就瞎了.当时也想算法应该接近常数级别的. 如果真的算必然跪.回头看了下解题报告. 话说比赛很喜欢考异或,"位"思想,组合问题 对于计算选取k个数字时候,分别计算各个位上可能出现的情况,然后计算各个位上的累加和.即便一个数字可由很多位组成但是每次计算一个位 记录每一位上1的个数(这里只需要32位),对于第i天,必须要选出奇数个1才能使该位异或结果位1,否则为0.我们来看样例, 4 1 2 10 1 这4个数的二进制表示分别为: 0

HDU - 4810 Wall Painting(组合数学)

Description Ms.Fang loves painting very much. She paints GFW(Great Funny Wall) every day. Every day before painting, she produces a wonderful color of pigments by mixing water and some bags of pigments. On the K-th day, she will select K specific bag

hdu 4810 Wall Painting

http://acm.hdu.edu.cn/showproblem.php?pid=4810 把每一个数转化二进制,然后统计n个数在每一位的1的个数.奇数个1异或才能得1,然后用组合数,计算. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int mod=1000003; 6 7 int n; 8 __int64 a[1100]

hdu 4932 Miaomiao&amp;#39;s Geometry(暴力枚举)

Miaomiao's Geometry                                                                              Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description There are N point on X-axis . Miaomiao would like

Hdu 4810

2014-05-02 15:53:50 题目连接 2013年南京现场赛的题目,现场的时候,排在我们前面的队伍基本都过了这题,我们后面的队伍也有不少过了这题,唯独我们没有.. 后来是Qingyu Shao想到了思路,然后就让他来敲,我记得当时是C(n,k)打表的时候出现了问题,好弱..于是乎就开始吃东西了. 回来之后就一直想A掉这题,但是一直没有思路.半年之后......今天问了下TYS,然后他给我讲了大体思路,才有点感觉. 大体思路:记录每一位上1的个数(这里只需要32位),对于第i天,必须要选

HDU 4081 Qin Shi Huang&#39;s National Road System(最小生成树+暴力枚举边)

题目大意:给你1000个点,每个点上有一个数目代表这个城市有多少人,让你把这N个点构成一颗生成树,你可以删除其中的任意一条边.让你求出一个比例A/B是的这个比例最大,A表示你删除那条边上两个城市的人口数之和,B表示的是去掉这条变这可生成树上其他的边的总长度. 解体思路:先求出来最小生成树,然后暴力枚举生成树的边,B=总数-这条边的长度.A = 将这条连断开之后左右集合中权值最大的两个数的和. 这样保证了B最小的情况下,去找最大的A,所以是可行的解.生成树的同时建边,然后dfs找最大值. PS:这

hdu 2721(字符串处理,位运算 暴力)

Persistent Bits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 201    Accepted Submission(s): 116 Problem Description WhatNext Software creates sequence generators that they hope will produce