题解 [ARC158D] Equation

Leasier

2023-03-14 20:06:41

Solution

下面 $x, y, z$ 无序。 首先是赛时想法: - 打表发现一定存在一组解使得 $x + y = p$。 - 当 $n$ 为偶数,设 $r = \frac{x}{z}$,则 $z = \frac{2r^{3n} + 1}{(2r^n + 1)(2r^{2n} + 1)}$;当 $n$ 为奇数,同样设 $r = \frac{x}{z}$,则 $z = \frac{1}{2r^{2n} + 1}$。 - 随机化 $r$ 直到解合法即可。 现在我们来考虑如何不随机化。 1. $n$ 为奇数 考虑钦定 $r = 2$,但是你会发现有时候 $2^{2n} \equiv -\frac{1}{2} \pmod p$ 导致无解。 考虑在无解时改 $r = 2$ 为 $r = 4$,由于 $4^{2n} \equiv \frac{1}{4} \not\equiv -\frac{1}{2} \equiv 2^{2n} \pmod p$,则此时一定有解。 2. $n$ 为偶数 首先给出结论: - 首先判掉 $p = 5, 11$ 的情况。 - 令 $r = 2$,每次按照前述方法求出对应的 $x, y, z$,如果解不合法则令 $r \leftarrow r^2$ 并继续。 - 可以证明一定有解,且尝试的 $r$ 的个数 $\leq 3$。 证明:首先,失败只可能有两种情况 $z$ 的某个分子或分母为 $0$ 或 $r = p - 1$。 对于第二种情况,由于 $r$ 可以表示成 $2^{2^k}$ 的形式,则 $p$ 此时只可能为费马质数。对三个需要检验的费马质数 $17, 257, 65537$ 进行了验证,均满足上述条件。 对于第一种情况,考虑在失败时分类讨论 $2r^n + 1, 2r^{2n} + 1, 2r^{3n} + 1$ 中哪个为 $0$。下面设 $r' = r^2$。 - $2r^n + 1 = 0$ 于是有 $(r')^n \equiv \frac{1}{4} \pmod p$,则 $2(r')^n + 1 \equiv \frac{3}{2} \not\equiv 0 \pmod p$,$2(r')^{2n} + 1 \equiv \frac{5}{4} \not\equiv 0 \pmod p$(注意我们判掉了 $p = 5$),$2(r')^{3n} + 1 \equiv \frac{33}{32} \not\equiv 0 \pmod p$(注意我们判掉了 $p = 11$)。于是自乘一次后一定合法。 - $2r^{2n} + 1 = 0$ 于是有 $(r')^{2n} \equiv \frac{1}{4} \pmod p$,则 $2(r')^{2n} + 1 \equiv \frac{3}{2} \not\equiv 0 \pmod p$;因为 $(r')^n \equiv \pm \frac{1}{2} \pmod p$,则 $2(r')^n + 1 \equiv 0 \operatorname{or} 2 \pmod p$,$2(r')^{3n} + 1 \equiv \frac{3}{4} \operatorname{or} \frac{5}{4} \not\equiv 0 \pmod p$。于是自乘一次后要么合法,要么转化为 $2r^n + 1 = 0$ 的情况。 - $2r^{3n} + 1 = 0$ 于是有 $(r')^{3n} \equiv \frac{1}{4} \pmod p$,则 $2(r')^{3n} + 1 \equiv \frac{3}{2} \not\equiv 0 \pmod p$;假定 $(r')^n = -\frac{1}{2}$,则 $(r')^{3n} \equiv -\frac{1}{8} \not\equiv \frac{1}{4} \pmod p$;假定 $(r')^{2n} = -\frac{1}{2}$,则 $(r')^{6n} \equiv -\frac{1}{8} \not\equiv \frac{1}{16} \pmod p$。于是自乘一次后一定合法。 综上,把 $n$ 分别为奇数和偶数的两种情况拼起来即可。 代码: ```cpp #include <iostream> #include <algorithm> using namespace std; typedef long long ll; ll ans[7]; inline ll quick_pow(ll x, ll p, ll mod){ ll ans = 1; while (p){ if (p & 1) ans = ans * x % mod; x = x * x % mod; p >>= 1; } return ans; } inline bool check(){ sort(ans + 1, ans + 4); return ans[1] != ans[2] && ans[2] != ans[3]; } int main(){ int t; cin >> t; for (int i = 1; i <= t; i++){ int n, p; cin >> n >> p; n %= p - 1; if (n % 2 == 0){ if (p == 5 || p == 11){ for (int j = 2; ; j++){ ans[1] = (quick_pow(j, (ll)n * 3, p) * 2 % p + 1) % p * quick_pow((quick_pow(j, n, p) * 2 % p + 1) % p * (quick_pow(j, n * 2, p) * 2 % p + 1) % p, p - 2, p) % p; ans[2] = ans[1] * j % p; ans[3] = p - ans[2]; if (check()) break; } } else { ll r = 2; do { ans[1] = (quick_pow(r, (ll)n * 3, p) * 2 % p + 1) % p * quick_pow((quick_pow(r, n, p) * 2 % p + 1) % p * (quick_pow(r, n * 2, p) * 2 % p + 1) % p, p - 2, p) % p; ans[2] = ans[1] * r % p; ans[3] = p - ans[2]; r = r * r % p; } while (!check()); } } else { ans[1] = quick_pow((quick_pow(2, n * 2, p) * 2 % p + 1) % p, p - 2, p); if (ans[1] == 0){ ans[1] = quick_pow((quick_pow(4, n * 2, p) * 2 % p + 1) % p, p - 2, p); ans[2] = ans[1] * 4 % p; } else { ans[2] = ans[1] * 2 % p; } ans[3] = p - ans[2]; check(); } for (int j = 1; j <= 3; j++){ cout << ans[j] << " "; } cout << endl; } return 0; } ```