传送门
学过
F
W
T
FWT
FWT 看到操作
2
2
2 不难可以联想到
F
W
T
FWT
FWT
考虑一遍
⊕
\oplus
⊕
F
W
T
FWT
FWT 会把
a
t
a_t
at 变成什么
a
t
′
=
(
(
−
1
)
b
i
t
c
o
u
n
t
(
x
&
t
)
+
(
−
1
)
b
i
t
c
o
u
n
t
(
y
&
t
)
)
a
x
a_t'=((-1)^{bitcount(x\&t)}+(-1)^{bitcount(y\&t)})a_x
at′=((−1)bitcount(x&t)+(−1)bitcount(y&t))ax
考虑这个东西
(
−
1
)
b
i
t
c
o
u
n
t
(
x
&
t
)
+
(
−
1
)
b
i
t
c
o
u
n
t
(
y
&
t
)
(-1)^{bitcount(x\&t)}+(-1)^{bitcount(y\&t)}
(−1)bitcount(x&t)+(−1)bitcount(y&t)
当
b
i
t
c
o
u
n
t
(
x
&
t
)
bitcount(x\&t)
bitcount(x&t) 和
b
i
t
c
o
u
n
t
(
y
&
t
)
bitcount(y\&t)
bitcount(y&t) 同奇偶时才有值
实际上就是
b
i
t
c
o
u
n
t
(
(
x
⊕
y
)
&
t
)
bitcount((x\oplus y)\&t)
bitcount((x⊕y)&t) 为偶数
而只需要知道互不相关的
n
n
n 个
t
t
t 就可以解出
x
⊕
y
x\oplus y
x⊕y
并且题目又是随机的,那么期望做
O
(
n
)
O(n)
O(n) 遍,询问次数期望
O
(
n
2
)
O(n^2)
O(n2)
一个小细节,
F
W
T
FWT
FWT 矩阵为
A
=
(
1
1
1
−
1
)
A=\begin{pmatrix}1 & 1 \\ 1 & -1\end{pmatrix}
A=(111−1),这玩意儿并不满足
A
A
T
=
I
AA^T=I
AAT=I
但是它满足
A
A
T
(
1
2
0
0
1
2
)
=
I
AA^T\begin{pmatrix}\frac{1}{2} & 0 \\ 0 & \frac{1}{2}\end{pmatrix}=I
AAT(210021)=I
所以只要令
A
=
(
1
2
1
2
1
2
−
1
2
)
A=\begin{pmatrix}\frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}}\end{pmatrix}
A=(212121−21) 就好了
# include "quantumbreak.h"
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double sq(1.0 / sqrt(2));
static vector <int> zero;
static double A[2][2];
static int cnt[1 << 20];
inline int Check(int v, int n) {
int i;
for (i = 0; i < zero.size(); ++i) if (cnt[v & zero[i]] & 1) return 0;
return 1;
}
int query_xor(int n, int t) {
int i, j, s = 1 << n, flg = 0;
memset(cnt, 0, sizeof(cnt)), zero.clear();
A[1][1] = -sq, A[0][0] = A[0][1] = A[1][0] = sq;
for (i = 0; i < s; ++i) cnt[i] = cnt[i >> 1] + (i & 1);
for (i = 1; i <= 23; ++i) {
for (j = 0; j < n; ++j) manipulate(A, j);
zero.push_back(query());
}
for (i = 1; i < s; ++i) if (Check(i, n)) return i;
return 233;
}