UOJ#328. 【UTR #3】量子破碎

传送门
学过 \(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((x\oplus y)\&t)\) 为偶数
而只需要知道互不相关的 \(n\)\(t\) 就可以解出 \(x\oplus y\)
并且题目又是随机的,那么期望做 \(O(n)\) 遍,询问次数期望 \(O(n^2)\)
一个小细节,\(FWT\) 矩阵为 \(A=\begin{pmatrix}1 & 1 \\ 1 & -1\end{pmatrix}\),这玩意儿并不满足 \(AA^T=I\)
但是它满足 \(AA^T\begin{pmatrix}\frac{1}{2} & 0 \\ 0 & \frac{1}{2}\end{pmatrix}=I\)
所以只要令 \(A=\begin{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;
}
posted @ 2019-02-15 17:10  Cyhlnj  阅读(263)  评论(0编辑  收藏  举报