P6610 - 同余方程 题解
一道卓越得让我五体投地的好题/ww
首先拆 CRT 是显然的吧()。将 \(p\) 拆成若干个奇质数 \(p_i\) 的乘积,设 \(a^2+b^2\equiv x\pmod{p_i}\) 的解集 \(X_i\)(是个二元组集合哟),则从每个 \(X_i\) 中选一组出来都能用 CRT 合并成一个模 \(p\) 的解,所以答案就是 \(\prod|X_i|\)(不需要写 CRT 哟)。
下面考虑 \(p\) 是奇质数怎么做。容易想到换元,令 \(y=a^2,z=b^2\),设 \(f(A)=[A\text{ 是模 }p\text{ 二次剩余哒!}]\),则答案就是 \(4\sum\limits_{y\not\equiv 0,y\not\equiv x}f(y)f(x-y)\),再加上 \(0\) 和 \(x\) 的贡献。后者是 trivial 的,考虑前者怎么求。
由于枚举条件是 \(y\not\equiv0,y\not\equiv x\),本能地分 \(x\) 是否为 \(0\) 讨论。如果等于那是比较简单的,设 \(m=\dfrac{p-1}2\),任取原根 \(g\),设 \(y\equiv g^\alpha\),则显然 \(-y\equiv -g^\alpha\equiv g^{m+\alpha}\)。如果 \(m\) 是偶数,那么 \(f(y)=f(-y)\),于是 sum 枚举的有一半都是 \(1\),算出来就是 \(4\times\dfrac{p-1}2=2(p-1)\);\(m\) 是奇数的话有 \(f(y)=1-f(-y)\),这两者永远不可能同时为 \(1\),那就寄了,算出来是 \(0\)。
\(x\not\equiv0\) 乍一看感觉很离谱,觉得不可做,因为加法和二次剩余放一块就像世纪难题(雾水)。但注意到二次剩余判定方法,\(f(A)=[A^{m}\equiv 1]\),这样 \(f(A)=0\) 对应 \(A^m\equiv-1\),\(f(A)=1\) 对应 \(A^m\equiv 1\),于是有 \(f(A)=\dfrac{(A^m+1)\bmod p}2\)!这样就把一个真值表达式变成了代数式!但一个问题是,要求的 \(\sum\) 是在 \(\Z\) 上的,而这样表示 \(f(A)\) 是在 \(\Z_p\) 上的,这就意味着如果按照这个表达式计算 \(\sum\),只能得到模 \(p\) 意义下的值。接下来是最神仙的地方:只需要知道模意义下的值,便可知道真实值,因为 \(\sum f(y)f(x-y)\in[0,p-2]\)!!!!
接下来就略显 trivial 了。忽略 \(f(A)\) 的分母,最后乘个 \(4\) 的逆元即可。显然
第四项的和显然是 \(p-2\)。第二三项是对称的,分别能取遍 \([1,p)\backslash \{x\}\),而 \([1,p)\) 的 \(m\) 次方一半是 \(1\) 一半是 \(-1\),总和就是 \(0\),所以取 \(-x^m\) 就行了。第一项的话,乘进去得到 \(\!\left(xy-y^2\right)^m\),除以 \(y^2\) 显然值不变,为 \(\left(\dfrac xy-1\right)^m\)。这就比较简单,\(\dfrac xy\) 显然取遍 \([2,p)\),于是 \(\dfrac xy-1\) 取遍 \([1,p-2]\)。
code
int solve(int p, int x) {
if(x == 0) return (p - 1) % 4 == 0 ? 2 * p - 1 : 1;
int m = p - 1 >> 1;
int ans = p - 2;
(ans += 2 * -qpow(x, m, p)) %= p;
(ans += -qpow(p - 1, m, p)) %= p;
ans = (ans + 10 * p) * inv(4, p) % p * 4;
return ans + 4 * (qpow(x, m, p) == 1);
}
void mian() {
int p = read(), x = read();
int ans = 1;
for(int i = 2; i * i <= p; ++i) if(p % i == 0) {
ans *= solve(i, x % i);
p /= i;
} if(p > 1) ans *= solve(p, x % p);
prt(ans), pc('\n');
}