D.Parity of Tuples
题目大意:
给一个n∗mn*mn∗m矩阵(a)ij(a)_{ij}(a)ij,行向量为viv_ivi, 求⊕x=02k(count(x)∗3x mod(109+7))\oplus_{x=0}^{2^k}(count(x) * 3^x\space mod(10^9+7))⊕x=02k(count(x)∗3x mod(109+7))
其中count(x)count(x)count(x)表示12m∑in∏jm(1−(−1)∣aij and x∣)\frac{1}{2^m} \sum_i^n \prod_j^m (1-(-1)^{|a_{ij} \space and \space x| })2m1∑in∏jm(1−(−1)∣aij and x∣), ⊕\oplus⊕表示异或,∣a∣|a|∣a∣表示a的二进制中1的个数。
数据范围:
1≤n≤1051 \leq n \leq 10^51≤n≤105
1≤m≤101 \leq m \leq 101≤m≤10
1≤k≤201 \leq k \leq 201≤k≤20
0≤ai,j<2k0 \leq a_{i,j} < 2^k0≤ai,j<2k
解题过程:
考虑化简以上count(x)count(x)count(x),由于(−1)∣a and x∣+∣b and x∣=(−1)∣(a ⊕ b) and x∣(-1)^{|a\space and \space x| + |b\space and\space x|}= (-1)^{|(a \space \oplus \space b) \space and \space x|}(−1)∣a and x∣+∣b and x∣=(−1)∣(a ⊕ b) and x∣
则展开∏\prod∏后得到:
12m∑in∑S⊆vi(−1)size(S)∗(−1)∣(⊕j∈Saij) and x∣
\frac{1}{2^m} \sum_i^n \sum_{S \subseteq {v_i}} (-1)^{size(S)} * (-1)^{|(\oplus_{\atop j \in S}a_{ij}) \space and \space x |}
2m1i∑nS⊆vi∑(−1)size(S)∗(−1)∣(⊕j∈Saij) and x∣
其中s为枚举每个行向量的二进制集合。
这里可以观察到和离散沃尔什变换相似的地方,即:
Ck=∑i⊕j=kAi∗BjC_k=\sum_{i\oplus j=k}A_i*B_jCk=∑i⊕j=kAi∗Bj
DWT(A)i=∑jnAj∗fi,jDWT(A)_i=\sum_j^nA_j*f_{i,j}DWT(A)i=∑jnAj∗fi,j
DWT(C)i=DWT(A)i∗DWT(B)iDWT(C)_i=DWT(A)_i*DWT(B)_iDWT(C)i=DWT(A)i∗DWT(B)i
⇒fi,j∗fi,k=fi,j⊕k\Rightarrow f_{i,j}*f_{i,k}=f_{i,j\oplus k}⇒fi,j∗fi,k=fi,j⊕k
⇒and:fi,j=[i and j==i]\Rightarrow and : f_{i,j}=[i\space and \space j == i]⇒and:fi,j=[i and j==i]
⇒or:fi,j=[i and j==j]\Rightarrow or : f_{i,j}=[i\space and \space j == j]⇒or:fi,j=[i and j==j]
⇒xor:fi,j=(−1)∣i and j∣\Rightarrow xor : f_{i,j}= (-1)^{| i \space and \space j |}⇒xor:fi,j=(−1)∣i and j∣
注意到xorxorxor的形式与上述形式完全一致,所以令
cntx=∑in∑S∈i(−1)size(S)cnt_x = \sum_i^n \sum_{S \in i} (-1)^{size(S)}cntx=i∑nS∈i∑(−1)size(S)
其中x=⊕j∈Sai,jx=\oplus_{\atop j \in S} a_{i,j}x=⊕j∈Sai,j,则对于cntcntcnt做沃尔什变换可得:
DWT(cnt)x=∑j2k∑in∑S⊆vi(−1)size(S)∗(−1)∣j and x∣
DWT(cnt)_x=\sum_j^{2^k}\sum_i^n\sum_{S \subseteq v_i} (-1)^{size(S)}*(-1)^{|j \ and \ x|}
DWT(cnt)x=j∑2ki∑nS⊆vi∑(−1)size(S)∗(−1)∣j and x∣
由此可得:
count(x)=12m∗DWT(cnt)xcount(x)=\frac{1}{2^m} *DWT(cnt)_xcount(x)=2m1∗DWT(cnt)x
预处理cntxcnt_xcntx复杂度O(n 2m)O(n\ 2^m)O(n 2m),FWTFWTFWT复杂度O(k 2k)O(k\ 2^k)O(k 2k),总复杂度为O(n 2m+k 2k)O(n \ 2^m + k \ 2^k)O(n 2m+k 2k)
// Cease to struggle and you cease to live
// D.cpp
// Created by Nickwzk
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0, ch = getchar(); bool fg = 1;
while(ch < '0' || ch > '9') { if(ch == '-') fg = 0; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return fg ? x : -x;
}
const int mod = 1e9 + 7;
void FWT(vector<int> &a,int n) {
for(int i = 2;i <= n; i <<= 1) {
for(int j = 0; j < n; j += i) {
for(int d = 0, w = i >> 1; d < w; d++){
int u = a[j + d], v = a[j + d + w];
a[j + d] = u + v, a[j + d + w] = u - v;
}
}
}
}
void dfs(vector<int> &cnt, const vector<int> &a, int i, int x, int p) {
if(i < a.size()) {
dfs(cnt, a, i + 1, x, p);
dfs(cnt, a, i + 1, x ^ a[i], -p);
}
else {
cnt[x] += p;
}
}
int main() {
int n, m, k;
while(~scanf("%d%d%d", &n, &m, &k)) {
auto cnt = vector<int>(1 << k, 0);
auto a = vector<int>(m);
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) a[j] = read();
dfs(cnt, a, 0, 0, 1);
}
FWT(cnt, 1 << k);
int ans = 0, pw = 1 << m, w = 1;
for(int x = 0; x < (1 << k); x++) {
ans ^= (long long)w * (cnt[x] / pw) % mod;
w = (long long)w * 3 % mod;
}
printf("%d\n", ans);
}
return 0;
}