Problem Statement
给定一个长度为N的集合,对其进行XOR_SUM(异或和)运算,定义为:计算它每个非空子集进行异或运算的结果之和,输出这个和% 109 + 7的结果。
一个集合的异或结果是其中所有元素的异或运算的结果
例如,集合{A,B,C}异或的结果 = ((A^B)^C), 其中 ^ 表示 异或运算XOR
。
因此, 对包含3个元素的集合A = {X1, X2, X3}进行异或和运算XOR_SUM可以如下进行:
所有非空子集是 {X1, X2, X3, (X1,X2), (X2,X3), (X1,X3), (X1,X2,X3)}
XOR_SUM(A) = X1 + X2 + X3 + X1^X2 + X2^X3 + X1^X3 + ((X1^X2)^X3)
输入格式
一个整数T表示测试数据组数,后面跟2T行。
每组测试数据包含两行, 第一行包含一个整数N
第二行包含N个空白分隔的整数
输出格式
T行每行,每行对应一组数据的结果。
约束条件
1 <= T <= 5
1 <= N <= 105
0 <= A[i] <= 109
输入样例 #00
1
3
1 2 3
输出样例 #00
12
解题思路:首先我们不能枚举所有的子集进行处理,那样肯定会TLE。因此我们采用枚举二进制位的方法进行计算,最多二进制位为第30位,我们计算每一位上的组合方案数即可,虽然题目中包含组合数取模,但是本题不需要。因为C(n,0)+C(n,2)+....=C(n,1)+C(n,3)+....=2^(n-1),直接套公式即可。
#include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <vector> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 100010; const int mod = 1000000000 + 7; //int arr[maxn][35]; int bit[40]; ll power_mod(ll a, ll b) { ll res = 1; while(b) { if(b&1) res = res * a % mod; a = a * a % mod; b >>= 1; } return res; } ll C(ll n, ll m) { if(m > n) return 0; ll ans = 1; for(int i = 1; i <= m; ++i) { ll a = (n + i - m) % mod; ll b = i % mod; ans = ans * (a * power_mod(b, mod - 2) % mod) % mod; } return ans; } ll lucas(ll n, ll m) { if(m == 0) return 1; return C(n % mod, m % mod) * lucas(n / mod, m / mod) % mod; } int main() { /* Enter your code here. Read input from STDIN. Print output to STDOUT */ int T, n, x; ll ans; scanf("%d", &T); while(T--) { ans = 0; scanf("%d", &n); memset(bit, 0, sizeof(bit)); for(int i = 0; i < n; ++i) { scanf("%d", &x); for(int j = 0; j <= 30; ++j) { if(x&(1<<j)) { bit[j]++; } } } for(int i = 0; i <= 30; ++i) { ll t = 0; if(bit[i] == 0) continue; t = (power_mod(2, bit[i]-1) * power_mod(2, n - bit[i]) % mod) * (1LL<<i) % mod; /* for(int j = 1; j <= bit[i]; j += 2) { t = t + ((C(bit[i], j) * power_mod(2, n - bit[i]) % mod) * (1LL<<i)) % mod; } */ ans = (ans + t) % mod; } cout << ans << endl; //printf("%I64d\n", ans); } return 0; }