链接:
题意:
给定n个正整数,a1 a2 ... an,从中选取k个数 , ai1 ai2 ai3 ... Aik,其中(1<=i1<i2<i3<...<ik<=n),u=ai1 ^ai2 ^ai3 ^... ^Aik,将异或和为u 的序列(i1,i2,...,ik)的个数记为f(u),求∑(f(u)*u) (枚举u从1到正无穷) ,由于数值可能非常大,输出对1000000007 取模后的余数(即结果mod 1000000007)。
题解:
统计每一位的1的个数,对于每一位,计算有多少种异或和为1的情况,只有有奇数个1的时候异或和才为1,所以就要用的组合数了
这个可以通过逆元快速求的C(n,m)
代码:
31 ll n, k;32 ll a[MAXN];33 ll b[MAXN];34 35 ll extgcd(ll a, ll b, ll &x, ll &y) {36 ll d = a;37 if (b) d = extgcd(b, a%b, y, x), y -= (a / b) * x;38 else x = 1, y = 0;39 return d;40 }41 42 ll inv(ll a) {43 ll x, y;44 extgcd(a, MOD, x, y);45 return (MOD + x%MOD) % MOD;46 }47 48 ll C(ll n, ll m) {49 if (n < m) return 0;50 ll ret = (b[n] * inv(b[m])) % MOD;51 ret = (ret*inv(b[n - m])) % MOD;52 return ret;53 }54 55 int main() {56 b[0] = 1;57 rep(i, 1, MAXN) b[i] = (b[i - 1] * i) % MOD;58 scanf("%d%d", &n, &k);59 rep(i, 0, n) scanf("%d", a + i);60 ll ans = 0;61 ll cnt = 1;62 rep(i, 0, 25) {63 ll a1 = 0;64 rep(j, 0, n) {65 if (a[j] & 1) a1++;66 a[j] >>= 1;67 }68 if (!a1) continue;69 ll a0 = n - a1;70 71 ll sum = 0;72 for (ll p = 1; p <= k; p += 2) {73 ll q = k - p;74 if (q > a0) continue;75 sum = (sum + C(a1, p) * C(a0, q)) % MOD;76 }77 ans = (ans + sum*cnt) % MOD;78 cnt <<= 1;79 }80 printf("%d\n", ans);81 return 0;82 }