D.Parity of Tuples
题目大意:
给一个
n
∗
m
n*m
n∗m矩阵
(
a
)
i
j
(a)_{ij}
(a)ij,行向量为
v
i
v_i
vi, 求
⊕
x
=
0
2
k
(
c
o
u
n
t
(
x
)
∗
3
x
m
o
d
(
1
0
9
+
7
)
)
\oplus_{x=0}^{2^k}(count(x) * 3^x\space mod(10^9+7))
⊕x=02k(count(x)∗3x mod(109+7))
其中
c
o
u
n
t
(
x
)
count(x)
count(x)表示
1
2
m
∑
i
n
∏
j
m
(
1
−
(
−
1
)
∣
a
i
j
a
n
d
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 ≤ 1 0 5 1 \leq n \leq 10^5 1≤n≤105
1 ≤ m ≤ 10 1 \leq m \leq 10 1≤m≤10
1 ≤ k ≤ 20 1 \leq k \leq 20 1≤k≤20
0 ≤ a i , j < 2 k 0 \leq a_{i,j} < 2^k 0≤ai,j<2k
解题过程:
考虑化简以上
c
o
u
n
t
(
x
)
count(x)
count(x),由于
(
−
1
)
∣
a
a
n
d
x
∣
+
∣
b
a
n
d
x
∣
=
(
−
1
)
∣
(
a
⊕
b
)
a
n
d
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
∏后得到:
1
2
m
∑
i
n
∑
S
⊆
v
i
(
−
1
)
s
i
z
e
(
S
)
∗
(
−
1
)
∣
(
⊕
j
∈
S
a
i
j
)
a
n
d
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为枚举每个行向量的二进制集合。
这里可以观察到和离散沃尔什变换相似的地方,即:
C k = ∑ i ⊕ j = k A i ∗ B j C_k=\sum_{i\oplus j=k}A_i*B_j Ck=∑i⊕j=kAi∗Bj
D W T ( A ) i = ∑ j n A j ∗ f i , j DWT(A)_i=\sum_j^nA_j*f_{i,j} DWT(A)i=∑jnAj∗fi,j
D W T ( C ) i = D W T ( A ) i ∗ D W T ( B ) i DWT(C)_i=DWT(A)_i*DWT(B)_i DWT(C)i=DWT(A)i∗DWT(B)i
⇒ f i , j ∗ f i , k = f i , j ⊕ k \Rightarrow f_{i,j}*f_{i,k}=f_{i,j\oplus k} ⇒fi,j∗fi,k=fi,j⊕k
⇒ a n d : f i , j = [ i a n d j = = i ] \Rightarrow and : f_{i,j}=[i\space and \space j == i] ⇒and:fi,j=[i and j==i]
⇒ o r : f i , j = [ i a n d j = = j ] \Rightarrow or : f_{i,j}=[i\space and \space j == j] ⇒or:fi,j=[i and j==j]
⇒ x o r : f i , j = ( − 1 ) ∣ i a n d j ∣ \Rightarrow xor : f_{i,j}= (-1)^{| i \space and \space j |} ⇒xor:fi,j=(−1)∣i and j∣
注意到
x
o
r
xor
xor的形式与上述形式完全一致,所以令
c
n
t
x
=
∑
i
n
∑
S
∈
i
(
−
1
)
s
i
z
e
(
S
)
cnt_x = \sum_i^n \sum_{S \in i} (-1)^{size(S)}
cntx=i∑nS∈i∑(−1)size(S)
其中
x
=
⊕
j
∈
S
a
i
,
j
x=\oplus_{\atop j \in S} a_{i,j}
x=⊕j∈Sai,j,则对于
c
n
t
cnt
cnt做沃尔什变换可得:
D
W
T
(
c
n
t
)
x
=
∑
j
2
k
∑
i
n
∑
S
⊆
v
i
(
−
1
)
s
i
z
e
(
S
)
∗
(
−
1
)
∣
j
a
n
d
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∣
由此可得:
c
o
u
n
t
(
x
)
=
1
2
m
∗
D
W
T
(
c
n
t
)
x
count(x)=\frac{1}{2^m} *DWT(cnt)_x
count(x)=2m1∗DWT(cnt)x
预处理
c
n
t
x
cnt_x
cntx复杂度
O
(
n
2
m
)
O(n\ 2^m)
O(n 2m),
F
W
T
FWT
FWT复杂度
O
(
k
2
k
)
O(k\ 2^k)
O(k 2k),总复杂度为
O
(
n
2
m
+
k
2
k
)
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;
}