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
bags of pigments and mix them to get a color of pigments which she will use that day. When she mixes a bag of pigments with color A and a bag of pigments with color B, she will get pigments with color A xor B.

When she mixes two bags of pigments with the same color, she will get color zero for some strange reasons. Now, her husband Mr.Fang has no idea about which K bags of pigments Ms.Fang will select on the K-th day. He wonders the sum of the colors Ms.Fang will
get with  different plans.

For example, assume n = 3, K = 2 and three bags of pigments with color 2, 1, 2. She can get color 3, 3, 0 with 3 different plans. In this instance, the answer Mr.Fang wants to get on the second day is 3 + 3 + 0 = 6.

Mr.Fang is so busy that he doesn’t want to spend too much time on it. Can you help him?

You should tell Mr.Fang the answer from the first day to the n-th day.

Input

There are several test cases, please process till EOF.

For each test case, the first line contains a single integer N(1 <= N <= 10 3).The second line contains N integers. The i-th integer represents the color of the pigments in the i-th bag.

Output

For each test case, output N integers in a line representing the answers(mod 10 6 +3) from the first day to the n-th day.

Sample Input

 4
1 2 10 1 

Sample Output

 14 36 30 8 

题意:给你n和k,求分别从n个中选择k个异或和

思路:首先知道0和1异或是不会影响结果的,只有1和1异或且1的个数是奇数的时候才会对结果产生影响,所以我们把每个数都转换成二进制,统计每一位上的1的个数,利用组合数学解决

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long ll;
using namespace std;
const int maxn = 1005;
const ll mod = 1000003;

ll C[maxn][maxn], ans[maxn];
int n, cnt[maxn];

void init() {
	for (int i = 0; i <= 1001; i++)
		C[i][0] = C[i][i] = 1;
	for (int i = 2; i <= 1001; i++)
		for (int j = 1; j < i; j++)
			C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;
}

void cal(int x) {
	int cur = 0;
	while (x) {
		if (x & 1)
			cnt[cur]++;
		cur++;
		x >>= 1;
	}
}

int main() {
	init();
	int x;
	while (scanf("%d", &n) != EOF) {
		memset(cnt, 0, sizeof(cnt));
		memset(ans, 0, sizeof(ans));
		for (int i = 1; i <= n; i++) {
			scanf("%d", &x);
			cal(x);
		}

		for (int i = 1; i <= n; i++)
			for (int j = 0; j < 32; j++)
				for (int k = 1; k <= i; k += 2) {
					ans[i] += (C[cnt[j]][k] % mod * C[n-cnt[j]][i-k] % mod) * (1<<j) % mod;
					ans[i] %= mod;
				}

		for (int i = 1; i < n; i++)
			printf("%lld ", ans[i]);
		printf("%lld\n", ans[n]);
	}
	return 0;
}
时间: 2024-10-23 23:39:16

HDU - 4810 Wall Painting(组合数学)的相关文章

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

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 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 (位操作-异或)

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【二进制+异或+暴力枚举】

给出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

hdu(2062)-Subset sequence 组合数学

题意:求集合{1,2,3...n}的第m个排列子集合.集合的大小按字典树排. 例两个元素的排列子集合按字典树排列是:{1},{1,2},{2},{2,1}: 解法:一个一个元素来确定,每次把剩余的元素按大小顺序排列在num中,然后根据排列组合原理直接计算下一个位置的元素的大小,直到排列数为0停止: 代码: /****************************************************** * author:xiefubao **********************

Hdu 4810

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

HDU 4909 String(组合数学)

HDU 4909 String 题目链接 题意:给定一个字符串全是小写字符,可能有一个位置为?,问号可以替代任何字符,也可以删掉,问有多少连续字串满足所有字母是偶数个 思路:组合数学,计算所有前最串的各个字母的奇偶状态,用一个01串表示,然后记录下个数,对于每个相同的状态,任选两个就能得到一个子序列,答案为所有C(num, 2)的和. 但是这个问题多了一个?的情况,但是没关系,可以枚举?,然后把序列分为3部分去考虑,?之前,?之后,和包含了?的串分开考虑即可 代码: #include <cstd

hdu 3037 Saving Beans(组合数学)

hdu 3037 Saving Beans 题目大意:n个数,和不大于m的情况,结果模掉p,p保证为素数. 解题思路:隔板法,C(nn+m)多选的一块保证了n个数的和小于等于m.可是n,m非常大,所以用到Lucas定理. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; ll n, m, p; ll qPow (ll a