洛谷 P6610 [Code+#7] 同余方程

\(\gdef\lcm{\operatorname{lcm}} \gdef\ord{\operatorname{ord}} \gdef\Z{\mathbb Z} \gdef\F{\mathbb F}\)

题目描述

给出若干组正整数 \(p\)\(x\),求方程 \(a^2+b^2 \equiv x \pmod p\) 关于 \(a\)\(b\) 在模 \(p\) 意义下解的组数,其中 \(p\) 是奇数,且不包含平方因子

题解

首先使用 CRT,将问题转化为模奇质数下的问题,最后结果相乘即可。

引入 \(i^2 = -1\),那么有 \(a^2 + b^2 = (a+bi)(a-bi) \equiv x \pmod p\)

我们知道 \(i \in \Z_p \iff \ord(i) \mid p-1 \iff p = 4k+1\),故以下分 \(p = 4k+1\)\(p = 4k+3\) 讨论。

\(p = 4k+1\) 时,令 \(u = a+bi\)\(v = a-bi\),则 \(u, v\)\(a, b\) 一一对应,要求的是 \(uv \equiv x \pmod p\) 的解数。
\(x = 0\) 时有 \(u = 0\)\(v = 0\),答案为 \(2p-1\)\(x \neq 0\) 时可以任意取 \(u\) 后唯一确定 \(v\),故答案为 \(p-1\)

\(p=4k+3\) 时,\(i \notin \Z_p\),故在 \(\Z_p[i]\) 上考虑。
我们定义范数 \(N(z) = z\bar{z}\),则 \(N(a+bi) = a^2+b^2\),容易验证 \(N(zw) = N(z)N(w)\),我们要求的就是 \(\Z_p[i]\) 中元素在范数映射下的原像大小。

\(\Z_p[i]\) 作为 \(p^2\) 个元素的有限域 \(\F_{p^2}\),有原根存在定理,即其乘法群为循环群。
设其一个原根为 \(\gamma\),我们证明,\(N(\gamma) = g\)\(\Z_p\) 的原根。

\(\Z_p[i]\) 作为 \(x^2+1\)\(\Z_p\) 上的分裂域,其 Galois 群为 \(i \mapsto -i\)
同时,\(\Z_p[i]\) 存在域扩张 \(\F_{p^2} / \F_p\),其 Galois 群为 Frobenius 自同构 \(x \mapsto x^p\)
对比可知 \((a+bi)^p = a-bi\),计算可以验证这个结果,故 \(N(z) = z\bar{z} = z z^p = z^{p+1}\)
\(g = \gamma^{p+1}\)。根据原根的定义 \(1, \gamma^{p+1}, \gamma^{2(p+1)}, \cdots\) 互不相同,故 \(g\)\(\Z_p\) 的原根。

然后就容易了,对于 \(i=0\sim p^2-2\)\(N(\gamma^i) = g^i\),也即 \(1 \sim p-1\) 各被取到 \((p^2-1)/(p-1) = p+1\) 次。剩下一个 \(N(0) = 0\)

代码:

#include <bits/stdc++.h>
using namespace std;
inline int Calc(int x, int p) { return p & 2 ? x ? p + 1 : 1 : x ? p - 1 : 2 * p - 1; }
void Solve() {
    int x, m, ans = 1; cin >> m >> x;
    for(int i = 2; i * i <= m; ++i)
        if(m % i == 0) ans *= Calc(x % i, i), m /= i;
    printf("%d\n", m == 1 ? ans : ans * Calc(x % m, m));
}
int main() {
    cin.tie(0)->sync_with_stdio(0);
    int T; cin >> T; while(T--) Solve();
}
posted @ 2024-02-22 08:34  JerryTcl  阅读(46)  评论(0)    收藏  举报