Hdu 4810

2014-05-02 15:53:50

题目连接

2013年南京现场赛的题目,现场的时候,排在我们前面的队伍基本都过了这题,我们后面的队伍也有不少过了这题,唯独我们没有。。

后来是Qingyu
Shao想到了思路,然后就让他来敲,我记得当时是C(n,k)打表的时候出现了问题,好弱。。于是乎就开始吃东西了。

回来之后就一直想A掉这题,但是一直没有思路。半年之后......今天问了下TYS,然后他给我讲了大体思路,才有点感觉。

大体思路:记录每一位上1的个数(这里只需要32位),对于第i天,必须要选出奇数个1才能使该位异或结果位1,否则为0。我们来看样例,

4

1 2 10 1

这4个数的二进制表示分别为:

0001

0010

1010

0001

比如第2天的时候,
从4个中选出2个来做异或,第4位上只有1个1,所以有3中选法可以使得这一位异或之后结果为1,(也就是C(3,1) *
C(1,1)),第3位的没有1,所以异或结果一定为0,第2位上又2个1,所以有4种选法,同理第一位上也是4种。

所以其结果就是 (1<<3)*C(3,1)
+ 0 * C(4,2) + (1<<1)*C(2,1)*C(2,1) +
(1<<0)*C(2,1)*C(2,1)

附上代码:


 1 /*************************************************************************
2 > File Name: 4810.cpp
3 > Author: Stomach_ache
4 > Mail: [email protected]
5 > Created Time: 2014年05月02日 星期五 15时20分16秒
6 > Propose:
7 ************************************************************************/
8
9 #include <cmath>
10 #include <string>
11 #include <cstdio>
12 #include <fstream>
13 #include <cstring>
14 #include <iostream>
15 #include <algorithm>
16 using namespace std;
17
18 typedef long long LL;
19 #define MOD (1000000+3)
20 #define MAX_N (1000+3)
21
22 int n;
23 int a[MAX_N], ans[MAX_N], c[MAX_N][MAX_N];
24
25 void
26 init() {
27 c[0][0] = c[1][0] = c[1][1] = 1;
28 for (int i = 2; i < MAX_N; i++) {
29 c[i][0] = 1;
30 for (int j = 1; j <= i; j++) {
31 c[i][j] = (c[i-1][j] + c[i-1][j-1]) % MOD;
32 }
33 }
34
35 return ;
36 }
37
38 void
39 count(int x) {
40 for (int i = 0; i < 32; i++) {
41 if (x & (1<<i)) {
42 a[i]++;
43 }
44 }
45
46 return ;
47 }
48
49 int
50 main(void) {
51 init();
52 while (~scanf("%d",&n)) {
53 memset(a, 0, sizeof(a));
54 for (int i = 0; i < n; i++) {
55 int tmp;
56 scanf("%d", &tmp);
57 count(tmp);
58 }
59
60 memset(ans, 0, sizeof(ans));
61 for (int i = 1; i <= n; i++) {
62 for (int j = 0; j < 32; j++) {
63 for (int k = 1; k <= a[j] && k <= i; k += 2) {
64 ans[i] = (ans[i] + (LL)c[n-a[j]][i-k]*c[a[j]][k]%MOD*((1 << j)%MOD) % MOD) % MOD;
65 }
66 }
67 }
68
69 for (int i = 1; i <= n; i++) {
70 printf("%d%c", ans[i], i == n ? ‘\n‘ : ‘ ‘);
71 }
72 }
73
74 return 0;
75 }

Hdu 4810,布布扣,bubuko.com

时间: 2024-12-20 12:36:36

Hdu 4810的相关文章

hdu 4810 思维题+二进制位规律+异或规律 213南京现场赛题

http://acm.hdu.edu.cn/showproblem.php?pid=4810 以前做过一些涉及异或的题,化为二进制形式,然后统计0,1个数是一种很常见的处理方法,但是在做这个题的时候居然没尝试,脑残啊...... 一开始看5s时限,感觉稍微暴力一点应该可以,于是YY的O(n^3)算法但是没去实现,明显超时啊,大致就是通过C(n,1)的组合可以在O(n^2)内处理出C(n,2)的组合,在通过C(n,2)处理出C(n,3)的组合....但是C(n,2)已经是n^2个数了,所以算法是O

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(组合数学)

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 (组合数学+二进制)

题目链接 下午比赛的时候没有想出来,其实就是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 这道题 是属于什么类型?

统计每一位出现1的个数  求组合数 直接贴代码 #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <ctime> #include <string> #define CL(a,b) memset(a,b,sizeof(a)) #define INF 0x3fffffff

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 3507 Print Article 斜率优化

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 4810    Accepted Submission(s): 1451 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique