hdu4810 Wall Painting
2015-08-19 14:58
387 查看
题目意思就是给定n(≤1000)个整数,要求输出对于所有整数k(1..n),该整数集合的所有元素个数为k的子集其元素的异或的和对M取模的值。
考虑所有包含于原集合的k子集的个数,当n=1000, k = 500的时候,(n, k)非常之大。
显然单个考虑某一k子集对和的贡献不是一个合适的切入点。
再仔细看看题目,要求的到底的是什么。
给定集合S, #(S) = n, 给定 k ≤ n, 求∑f(A) % M, 其中A ⊆ S,且 #(A) = k, f(A) = ^A[i], (A[i] ∈ A)。
我们用长度足够大(记为len)的二进制数重写整数(对于本题长度大于32即可),假设整数a = str_A(binary form)
那么a^b = str_A ^ str_B = ∑(1 << i) * ((str_A[i] + str_B[i]) % 2) (i < len)。
也就是说,依次考察二进制串的每一位,若两个整数在该位上1的个数之和为奇数,则向两数异或中该位置贡献1,否则贡献0。
则f(A) = ^A[i] = ^ str_A[i] = ∑(1 << j) * (∑str_A[i][j] % 2) (j < len)。
到这里距离答案只有一步之遥了。
下面的问题在于怎么求∑f(A)。
这是一个求和,我们把j放在最外层循环。
那么我们有∑f(A)
= ∑(∑(1 << j) * (∑str_A[i][j] % 2)) (j < len)
= (1 << j) * ∑(∑str_A[i][j] % 2) ( j < len, str_A[i] 代表属于集合A中一个整数对应的二进制串,#(A) = k )
我们现在只考虑第j位上的情况。
我们知道每一个k子集最多向j位上贡献1,我们考虑所有k子集向j位上贡献多少。
假设原集合S中的数在第j位上依次是c[0], c[1], ..., c[n - 1], 其中c[i]非0即1。
也就是我们向这n个数中取k个数,数一数取得的数中1有奇数个还是偶数个,若为奇数个则贡献1,否则贡献0。
我们假设n个数中1的个数为p, 0的个数为 n - p。
那么所有k子集在该位上的贡献值应该是(p, 1) * (n - p, k - 1) + (p, 3) * (n - p, k - 3) +...
具体过程见代码。
acm.hdu.edu.cn/showproblem.php?pid=4810
View Code
考虑所有包含于原集合的k子集的个数,当n=1000, k = 500的时候,(n, k)非常之大。
显然单个考虑某一k子集对和的贡献不是一个合适的切入点。
再仔细看看题目,要求的到底的是什么。
给定集合S, #(S) = n, 给定 k ≤ n, 求∑f(A) % M, 其中A ⊆ S,且 #(A) = k, f(A) = ^A[i], (A[i] ∈ A)。
我们用长度足够大(记为len)的二进制数重写整数(对于本题长度大于32即可),假设整数a = str_A(binary form)
那么a^b = str_A ^ str_B = ∑(1 << i) * ((str_A[i] + str_B[i]) % 2) (i < len)。
也就是说,依次考察二进制串的每一位,若两个整数在该位上1的个数之和为奇数,则向两数异或中该位置贡献1,否则贡献0。
则f(A) = ^A[i] = ^ str_A[i] = ∑(1 << j) * (∑str_A[i][j] % 2) (j < len)。
到这里距离答案只有一步之遥了。
下面的问题在于怎么求∑f(A)。
这是一个求和,我们把j放在最外层循环。
那么我们有∑f(A)
= ∑(∑(1 << j) * (∑str_A[i][j] % 2)) (j < len)
= (1 << j) * ∑(∑str_A[i][j] % 2) ( j < len, str_A[i] 代表属于集合A中一个整数对应的二进制串,#(A) = k )
我们现在只考虑第j位上的情况。
我们知道每一个k子集最多向j位上贡献1,我们考虑所有k子集向j位上贡献多少。
假设原集合S中的数在第j位上依次是c[0], c[1], ..., c[n - 1], 其中c[i]非0即1。
也就是我们向这n个数中取k个数,数一数取得的数中1有奇数个还是偶数个,若为奇数个则贡献1,否则贡献0。
我们假设n个数中1的个数为p, 0的个数为 n - p。
那么所有k子集在该位上的贡献值应该是(p, 1) * (n - p, k - 1) + (p, 3) * (n - p, k - 3) +...
具体过程见代码。
acm.hdu.edu.cn/showproblem.php?pid=4810
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef __int64 LL; const int maxn = 1e3 + 10; const int mod = 1e6 + 3; int n; int s[maxn]; LL c[maxn][maxn]; int ans[maxn]; void init(){ memset(c, 0, sizeof c); c[0][0] = c[1][0] = c[1][1] = 1; for(int i = 2; i <= 1000; i++){ c[i][0]= c[i][i] = 1; int mid = i / 2; for(int j = 1; j <= mid; j++){ c[i][i - j] = c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; } } } void solve(){ memset(ans, 0, sizeof ans); for(int i = 30; i >= 0; i--){ int f = 1 << i; int cnt = 0; for(int j = 0; j < n; j++) if(s[j] & f) ++cnt; f %= mod; for(int j = 1; j <= n; j++){ for(int k = 1; k <= cnt && k <= j; k += 2){ ans[j - 1] += ((c[cnt][k] * c[n - cnt][j - k]) % mod * f) % mod; ans[j - 1] %= mod; } } } printf("%d", ans[0]); for(int i = 1; i < n; i++) printf(" %d", ans[i]); printf("\n"); } int main(){ init(); while(~scanf("%d", &n)){ for(int i = 0; i < n; i++) scanf("%d", &s[i]); solve(); } return 0; } /* 0001 0010 1010 0001 */
View Code
相关文章推荐
- pthread_cond_signal与pthread_cond_wait详解
- common.io中Tailer类读取文件内容乱码问题解决
- HDU 1022.Train Problem I【栈的应用】【8月19】
- 2015 Multi-University Training Contest 7 hdu 5378 Leader in Tree Land
- zyyy123 dongtaineibiao1234
- HDU3411Snail Alice(递推+矩阵快速幂)
- [Email] 收发邮件的协议 : IMAP and SMTP , POP3 and SMTP
- 2015 Multi-University Training Contest 9 hdu 5396 Expression
- codeforces 519C C. A and B and Team Training(枚举)
- 2015 HUAS Summer Trainning #6~O
- HDU 1302 The Snail
- 出现( linker command failed with exit code 1)错误总结
- 如何搞定foxmail下的.eml文件导入到win7内的outlook2007
- jboss eap 6.3 域(Domain)模式配置
- XML 包含函数fn:contains(string1,string2)的用法
- 华为OJ(Redraiment的走法)
- 【android学习笔记】理解android.intent.action.MAIN 与 android.intent.category.LAUNCHER
- 2015 Multi-University Training Contest 9-1007 Travelling Salesman Problem
- Communications link failure Last packet sent to the server was 0 ms ago.问题解决
- HDU 5402 Travelling Salesman Problem (2015 Multi-University Training Contest 9 2015多校联合)