传送门
学过 (FWT) 看到操作 (2) 不难可以联想到 (FWT)
考虑一遍 (oplus) (FWT) 会把 (a_t) 变成什么
(a_t'=((-1)^{bitcount(x&t)}+(-1)^{bitcount(y&t)})a_x)
考虑这个东西 ((-1)^{bitcount(x&t)}+(-1)^{bitcount(y&t)})
当 (bitcount(x&t)) 和 (bitcount(y&t)) 同奇偶时才有值
实际上就是 (bitcount((xoplus y)&t)) 为偶数
而只需要知道互不相关的 (n) 个 (t) 就可以解出 (xoplus y)
并且题目又是随机的,那么期望做 (O(n)) 遍,询问次数期望 (O(n^2))
一个小细节,(FWT) 矩阵为 (A=egin{pmatrix}1 & 1 \ 1 & -1end{pmatrix}),这玩意儿并不满足 (AA^T=I)
但是它满足 (AA^Tegin{pmatrix}frac{1}{2} & 0 \ 0 & frac{1}{2}end{pmatrix}=I)
所以只要令 (A=egin{pmatrix}frac{1}{sqrt{2}} & frac{1}{sqrt{2}} \ frac{1}{sqrt{2}} & -frac{1}{sqrt{2}}end{pmatrix}) 就好了
# 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;
}