【UTR #3】量子破碎

一道有趣的题。

看到按位的矩阵运算,如果对FWT比较熟悉的话,会比较容易地想到。

这种形式也就FWT等转移里面有吧……就算有其他的也难构造出来。

然而FWT的矩阵并不是酉矩阵(也就是满足 \(AA^T = I\)),这个很好办,就直接把行列式除到 \(1\) 就好了。

于是得到转移矩阵:

\[A = \left[ \begin{matrix} \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}} \end{matrix} \right] \]

我们接下来肯定是要做FWT了,显然,对所有 \(i\) 都做一遍 manipulate(A, i)

得到的东西肯定有性质。我们直接带入FWT的定义式进行展开,得到第 \(i\) 位的值为

\[\left(\frac{1}{\sqrt{2}}\right)^n \left( \left(-1\right)^{|x \cap i|} + \left(-1\right)^{|y \cap i|} \right) \]

显然,要么这一位为 \(0\),要么为 $ \pm 2 \left(\frac{1}{\sqrt{2}}\right)^n $。

我们考虑不为零的情况,因为只有这样才有用。

\[\begin{align*} |x \cap i| + |y \cap i| & \equiv 0 \pmod 2\\ |\left(x \cap i\right) \oplus \left(y \cap i\right)| & \equiv 0 \pmod 2\\ |\left(x \oplus y \right) \cap i| & \equiv 0 \pmod 2\\ \end{align*} \]

于是我们得到了 \(x \oplus y\) 这个定值。这个定值和我们查询得到的 \(i\) 的关系就是交大小为偶数。

那么我们不断FWT然后询问 \(i\),因为答案随机,猜测很快能随机出。

下面有两种做法,要么用异或方程组动态高斯消元,要么暴力。

然后我写的是暴力,具体就是得到一个 \(i\) 就把所有可能满足条件的都标上,直到剩下一个数就是答案。 具体可以用一个bool数组,然后每次and。

但是有一个问题,\(0\) 一直都满足,这样会有两个满足,导致死循环。因为题目保证 \(x \neq y\),所以 \(0\) 一开始就是不可能的。这样就可以唯一确定一个了。

因为期望查询次数为 \(O\left(n\right)\),常数很小(这个我是真的不会算

所以期望询问次数 \(O\left(n^2\right)\),除交互库复杂度 \(O\left(n2^n\right)\) 可以通过此题。

#include "quantumbreak.h"
#include <bits/stdc++.h>

const double is2 = 1 / sqrt(2);
double qry[2][2] = {
	{is2, is2},
	{is2, -is2}
};
int rest, can[1 << 16], iss[1 << 16];
int query_xor(int n, int _) {
	const int U = 1 << n;
	rest = U - 1;
	for (int i = 0; i != U; ++i) {
		iss[i] = __builtin_popcount(i) & 1 ^ 1;
		can[i] = true;
	}
	can[0] = false;
	while (rest > 1) {
		for (int i = 0; i != n; ++i)
			manipulate(qry, i);
		int x = query();
		rest = 0;
		for (int i = 0; i != U; ++i)
			rest += (can[i] &= iss[i & x]);
	}
	for (int i = 0; i != U; ++i)
		if (can[i])
			return i;
}
posted @ 2019-10-08 22:32  daklqw  阅读(220)  评论(0编辑  收藏  举报