「解题报告」ARC158D Equation
好神仙的题。
考虑形如 \(F(x, y, z) = x^i + y^i + z^i\) 的函数有一个性质:\(F(tx, ty, tz) = t^i F(x, y, z)\)。
原式要求 \((x+y+z)(x^n+y^n+z^n)(x^{2n}+y^{2n}+z^{2n})\equiv x^{3n}+y^{3n}+z^{3n}\),假如我们令 \(x = ta, y = tb, z = tc\),那么有 \(t^{3n+1}(a+b+c)(a^n+b^n+c^n)(a^{2n}+b^{2n}+c^{2n})\equiv t^{3n}(a^{3n}+b^{3n}+c^{3n})\)。
那么假如我们有一个 \((a, b, c)\),满足 \((a+b+c)(a^n+b^n+c^n)(a^{2n}+b^{2n}+c^{2n}) \ne 0\) 且 \(a^{3n}+b^{3n}+c^{3n}\),那么我们就能计算出 \(t\),那么 \((x, y, z) = (ta, tb, tc)\) 就是一组答案。
我们可以每次随机 \((a, b, c)\),然后判定答案合不合法即可。
我们可以证明,随机一次成功的概率大于等于 \(\frac{3}{4}\)。
考虑我们要满足的性质:
- \(a \ne b \ne c\)
- \(a^i + b^i + c^i \ne 0, \forall i \in \{1, n, 2n, 3n\}\)
前者概率为 \(O(\frac{1}{p})\),考虑后者。
我们可以证明,\(a^i + b^i + c^i = 0\) 的概率小于等于 \(\frac{1}{4}\)。
我们设 \(S\) 集合为所有的非零的 \(a^i\) 的取值,那么分几种情况:
设 \(m\) 为 \(S\) 集合的大小,可以发现,如果 \(x \in S\),那么 \(x^k \in S\),那么实际上 \(S\) 就是某个单位根集合,即有 \(x^m \equiv 1\)。
- \(m = 1 / 2\):那么说明 \(S = \{1\} / \{\pm 1\}\),由于 \(p \ge 5\),可以发现不可能等于 \(0\);
- \(m = 3\):说明有三个数 \((x, y, z)\),且 \(x + y + z = 0\),由于 \(x^3 \equiv 1\),且 \(p \ge 5\),那么有 \((-2x)^3 \ne 1\),即 \(-2x \ne 1\),则 \(x^3 - (-2y)^3 \ne 0\),即 \(x + 2y \ne 0\),这意味着如果有两个相同的数,和一定不等于 \(0\)。那么随机选取三个数,两两不相同的概率就是 \(\frac{3!}{3^3} = \frac{6}{27} < \frac{1}{4}\);
- \(m \ge 4\):那么固定 \((a, b)\),假如 \(-a^i-b^i \not \in S\),那么不可能等于 \(0\);否则,选中这个数的概率为 \(\frac{1}{m} \le \frac{1}{4}\)。
综上可知等于 \(0\) 的概率为 \(\frac{1}{4}\)。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005, P = 998244353;
int T;
int n, p;
mt19937 rd(chrono::system_clock::now().time_since_epoch().count());
int Rand(int l, int r) {
return uniform_int_distribution<int>(l, r)(rd);
}
long long qpow(int a, long long b) {
int ans = 1;
while (b) {
if (b & 1) ans = 1ll * ans * a % p;
a = 1ll * a * a % p;
b >>= 1;
}
return ans;
}
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &p);
while (true) {
long long a = Rand(1, p - 1), b = Rand(1, p - 1), c = Rand(1, p - 1);
if (a == b || a == c || b == c) continue;
int x = (a + b + c) * (qpow(a, n) + qpow(b, n) + qpow(c, n)) % p * (qpow(a, 2ll * n) + qpow(b, 2ll * n) + qpow(c, 2ll * n)) % p;
int y = (qpow(a, 3ll * n) + qpow(b, 3ll * n) + qpow(c, 3ll * n)) % p;
if (x != 0 && y != 0) {
int t = 1ll * y * qpow(x, p - 2) % p;
vector<long long> ans = { 1ll * a * t % p, 1ll * b * t % p, 1ll * c * t % p };
sort(ans.begin(), ans.end());
printf("%lld %lld %lld\n", ans[0], ans[1], ans[2]);
break;
}
}
}
return 0;
}