QOJ.ac

QOJ

Limite de temps : 2 s Limite de mémoire : 512 MB Points totaux : 100 Interactif

#13105. 交互式证明

Statistiques

这是一个交互式问题。

交互式证明的概念由 Goldwasser、Micali 和 Rackoff 在 1985 年引入计算复杂性理论。该系统涉及两方:证明者(Prover)和验证者(Verifier),它们都能访问一个公共字 $x$。验证者想要确定 $x$ 是否属于某个集合 $L$,而证明者想要说服验证者确实如此。验证者是一个必须在多项式时间内运行的随机化程序,而证明者的时间和内存不受限制。证明者和验证者通过互相发送消息进行交互,最后由验证者决定接受或拒绝。

验证者的目标是仅在 $x$ 确实属于 $L$ 时才接受。证明者的目标是强制验证者接受。该证明系统通常必须满足以下条件:如果 $x \in L$,证明者可以以高概率使验证者接受;如果 $x \notin L$,无论证明者如何努力,验证者接受的概率都可忽略不计。

在本题中,我们研究 #SAT 问题的一种重要交互式证明协议的性质。

令 $\varphi$ 为一个包含 $n$ 个布尔变量 $x_1, \dots, x_n$ 的布尔公式。允许的操作包括逻辑或(记作 |)、逻辑与(记作 &)和逻辑非(记作 !)。操作符按优先级从低到高排列,括号可用于改变运算优先级。例如,考虑公式 $\varphi(x_1, x_2) = x_1 \& x_2 | !x_1 \& !x_2$。

我们用 $0$ 表示假(false),$1$ 表示真(true)。如果布尔向量 $(a_1, \dots, a_n)$ 在设置 $x_i = a_i$ 后使得 $\varphi$ 的值为 $1$,则称该向量满足 $\varphi$。例如,向量 $(0, 0)$ 和 $(1, 1)$ 满足上述公式 $\varphi$,而 $(1, 0)$ 和 $(0, 1)$ 不满足。满足条件的向量个数称为 $\varphi$ 的权重,记作 $w(\varphi)$,因此 $w(\varphi) = 2$。

我们现在考虑证明 $w(\varphi) = k$ 的正确交互协议。从形式上定义语言 $\#SAT = \{(\varphi, k) \mid w(\varphi) = k\}$,并证明 $(\varphi, k) \in \#SAT$。

首先,证明者和验证者选择一个足够大的素数 $p$。所有后续计算均在模 $p$ 意义下进行。对于布尔公式 $\varphi$,其算术化 $A(\varphi)$ 递归定义如下:

  • 如果 $y$ 是变量,则 $A(y) = y$。
  • 如果 $\varepsilon$ 是公式且 $\varphi = !\varepsilon$,则 $A(\varphi) = 1 - A(\varepsilon)$。
  • 如果 $\vartheta$ 和 $\varepsilon$ 是公式且 $\varphi = \vartheta \& \varepsilon$,则 $A(\varphi) = A(\vartheta) \cdot A(\varepsilon)$。
  • 如果 $\vartheta$ 和 $\varepsilon$ 是公式且 $\varphi = \vartheta | \varepsilon$,则 $A(\varphi) = 1 - (1 - A(\vartheta)) \cdot (1 - A(\varepsilon))$。

例如,$A(\varphi) = 1 - (1 - x_1 x_2)(1 - (1 - x_1)(1 - x_2))$。 容易看出,如果 $(a_1, \dots, a_n)$ 是 $\varphi$ 的一个满足赋值,则 $A(\varphi)(a_1, \dots, a_n) = 1$,否则 $A(\varphi)(a_1, \dots, a_n) = 0$。因此: $$w(\varphi) = \sum_{x_1=0}^{1} \dots \sum_{x_n=0}^{1} A(\varphi)(x_1, \dots, x_n)$$

证明 $w(\varphi) = k$ 的过程分为 $n$ 个步骤。 在第一步中,考虑函数: $$P_1(x_1) = \sum_{x_2=0}^{1} \dots \sum_{x_n=0}^{1} A(\varphi)(x_1, \dots, x_n)$$ 该函数是关于 $x_1$ 的多项式:$P_1(x_1) = c_{1, d_1} x_1^{d_1} + c_{1, d_1-1} x_1^{d_1-1} + \dots + c_{1, 1} x_1 + c_{1, 0}$。显然,$P_1(0) + P_1(1) = k$。证明者通过发送 $d_1$ 以及系数 $c_{1, d_1}, \dots, c_{1, 0}$ 将 $P_1$ 发送给验证者。验证者检查 $P_1(0) + P_1(1) = k$,并随机选择一个 $0$ 到 $p-1$ 之间的整数 $r_1$ 发送给证明者。

现在开始第二步。考虑函数: $$P_2(x_2) = \sum_{x_3=0}^{1} \dots \sum_{x_n=0}^{1} A(\varphi)(r_1, x_2, \dots, x_n)$$ 注意 $x_1$ 已被替换为参数 $r_1$。该函数又是关于 $x_2$ 的多项式,因此证明者将此多项式发送给验证者。验证者检查 $P_2(0) + P_2(1) = P_1(r_1)$,并随机选择一个 $0$ 到 $p-1$ 之间的整数 $r_2$ 发送给证明者。

一般地,对于 $i$ 从 $2$ 到 $n-1$ 的第 $i$ 步,考虑函数: $$P_i(x_i) = \sum_{x_{i+1}=0}^{1} \dots \sum_{x_n=0}^{1} A(\varphi)(r_1, \dots, r_{i-1}, x_i, x_{i+1}, \dots, x_n)$$ 该函数是关于 $x_i$ 的多项式,证明者将其发送给验证者。验证者检查 $P_i(0) + P_i(1) = P_{i-1}(r_{i-1})$,随机选择 $r_i \in {0, \dots, p-1}$ 并发送给证明者。

最后一步略有不同。函数: $$P_n(x_n) = A(\varphi)(r_1, \dots, r_{n-1}, x_n)$$ 被发送给验证者。验证者检查 $P_n(0) + P_n(1) = P_{n-1}(r_{n-1})$,选择随机数 $r_n \in {0, \dots, p-1}$ 并检查 $A(\varphi)(r_1, \dots, r_n) = P_n(r_n)$ 是否成立。

请再次注意,所有计算均在模 $p$ 意义下进行。

如果验证者的所有测试均成功,则证明被接受。如果至少有一个测试失败,则证明被拒绝。可以证明,如果 $A(\varphi)$ 的次数为 $d$,则证明被接受但 $w(\varphi) \neq k$ 的概率最多为 $1 - (1 - d/p)^n$,因此通过选择足够大的 $p$,该值可以变得微不足道。

该证明协议的核心思想是,通过在 $\varphi$ 的算术化中代入模 $p$ 的随机整数,而不是仅仅代入 $0$ 和 $1$,来降低证明者强制验证者接受错误陈述的概率。如果验证者只选择 $0$ 或 $1$ 作为 $r_i$,证明者可以轻易欺骗验证者,即使在 $w(\varphi) \neq k$ 时也能以高概率强制其接受。这正是你在本题中需要做的。

你的程序将扮演证明者,试图强制评审团的验证者接受错误的陈述 $w(\varphi) = k$。验证者将遵循上述协议,但有一个例外:它将选择 $r_i \in \{0, 1\}$。我们将使用 $p = 239$。

交互

你的程序在每次运行中必须进行多次证明。如果你的程序成功在至少 $1/2$ 的案例中强制验证者接受,则会被接受。

每个证明开始时,你的程序从标准输入读取 $n$($\varphi$ 中的变量个数,$2 \le n \le 7$)。如果 $n=0$,则表示测试运行结束,你的程序必须终止。如果 $n > 0$,则证明开始。

下一行包含 $\varphi$ 的公式。公式使用以下字符:&|!() 以及 x 后面紧跟其从 $1$ 到 $n$ 的索引。空格可以自由分隔公式部分,但 x 与其索引之间不会被分隔。公式长度最多为 $100$ 个字符。

下一行包含 $k$,你的程序必须尝试证明 $w(\varphi) = k$,即使事实并非如此($0 \le k \le 2^n$)。

读取 $n$、$\varphi$ 和 $k$ 后,你的程序必须通过向验证者发送 $P_1$ 来开始协议。 它必须向标准输出打印次数 $d_1$,随后打印 $c_{1, d_1}, \dots, c_{1, 0}$。数字之间用空格或换行符分隔,在最后一个数字后打印换行符并刷新标准输出。

所有多项式的次数不得超过 $20$。所有系数必须在 $0$ 到 $238$ 之间。对于本题,常数零多项式的次数为 $0$。

验证者检查条件 $P_1(0) + P_1(1) = k$,并打印 $r_1$,你必须从标准输入读取它,$r_1$ 将为 $0$ 或 $1$。 之后,你必须以相同的格式发送 $P_2$,读取 $r_2$,依此类推。 发送 $P_n$ 后,你无需再为该测试用例等待任何输入,并继续处理下一个测试用例。

即使验证者执行的测试之一失败,验证者也不会终止协议。因此,即使你的程序发现无法欺骗验证者,也必须运行协议的所有 $n$ 轮。但是,不允许打印不正确的多项式(次数错误或系数错误)。

对于每个测试,你的程序将被要求进行至少 $64$ 次且最多 $128$ 次证明,如果在此测试用例中至少在 $1/2$ 的案例中欺骗了验证者,则会被接受。唯一的例外是样例测试,其中只有 $1$ 次运行,只要程序遵循交互协议,无论如何都会被接受。

保证验证者的回答不依赖于证明者发送的多项式。

样例

输入 1

2
x1 & x2 | !x1 & !x2
3
0
0

输出 1

1
1 1
1
238 1

在上面的例子中,协议进行如下。正确的 $P_1(x_1)$ 是 $P_1(x_1) = 1$。然而,证明者不能将其发送给验证者,因为 $P_1(0) + P_1(1) = 2$,但它需要证明 $w(\varphi) = 3$(当然这是错误的)。因此,证明者发送了不正确的多项式 $P_1(x_1) = x_1 + 1$,它满足 $P_1(0) + P_1(1) = 3$。验证者检查这一点并选择 $r_1 = 0$。

现在证明者发送 $P_2(x_2) = -x_2 + 1$,或者由于所有计算均在模 $239$ 下进行,$P_2(x_2) = 238x_2 + 1$。验证者检查 $P_2(0) + P_2(1) = P_1(0) = 1$。现在它选择 $r_2$ 为 $0$ 或 $1$,并检查 $A_\varphi(0, r_2) = P_2(r_2)$ 是否成立。幸运的是,对于证明者来说,$r_2 = 0$ 和 $r_2 = 1$ 时均成立,因此无论验证者最后如何选择,它都会接受。目标达成,验证者被欺骗了。

标准输入的最后一个 $0$ 表示测试运行结束,因此证明者终止。

Discussions

About Discussions

The discussion section is only for posting: General Discussions (problem-solving strategies, alternative approaches), and Off-topic conversations.

This is NOT for reporting issues! If you want to report bugs or errors, please use the Issues section below.

Open Discussions 0
No discussions in this category.

Issues

About Issues

If you find any issues with the problem (statement, scoring, time/memory limits, test cases, etc.), you may submit an issue here. A problem moderator will review your issue.

Guidelines:

  1. This is not a place to publish discussions, editorials, or requests to debug your code. Issues are only visible to you and problem moderators.
  2. Do not submit duplicated issues.
  3. Issues must be filed in English or Chinese only.
Active Issues 0
No issues in this category.
Closed/Resolved Issues 0
No issues in this category.