\quad 给出一个式子 x 2 ≡ n ( m o d p ) x^2≡n(mod p) x2≡n(modp),再给出 n n n和 p p p,如果能求得一个x满足该式子,即 x x x满足 x 2 = n + k p , k ∈ Z x^2=n+kp,k\in Z x2=n+kp,k∈Z,那么我们称 n n n是模 p p p的二次剩余,若不存在这样的 x x x,那么我们称 n n n是摸 p p p的非二次剩余。同时我们称 x x x为该二次同余方程的解。
\quad 对于一个数 n n n,如果我们要求 n ( m o d p ) \sqrt{n}(modp) n(modp)的值,那么我们可以看 n n n是否是模 p p p的二次剩余,如果是就会满足 x 2 ≡ n ( m o d p ) − > x ≡ n ( m o d p ) x^2≡n(mod p)->x≡\sqrt{n}(modp) x2≡n(modp)−>x≡n(modp),我们可以用 x x x来代替 n \sqrt{n} n,即只需要求该二次同余方程的解即可。
就是如果该二次同余方程有解的话,那么 n n n可以在摸 p p p的情况下开根号。
\quad 对于二次同余方程 x 2 ≡ n ( m o d p ) x^2≡n(mod p) x2≡n(modp),一共有 p − 1 2 + 1 \frac{p-1}{2}+1 2p−1+1个 n n n的值可以让方程有解,其中 + 1 +1 +1代表的是 n = 0 n=0 n=0的情况,此时 x = 0 x=0 x=0方程显然成立。
证明:
假设 u 2 = a p + k u^2=ap+k u2=ap+k即 u 2 ≡ k ( m o d p ) u^2≡k(mod p) u2≡k(modp)
因为: ∀ n ∈ Z , ( u + n p ) 2 = u 2 + n 2 p 2 + 2 u n p = ( a + n 2 p + 2 u n ) p + k \forall n \in Z,(u+np)^2=u^2+n^2p^2+2unp=(a+n^2p+2un)p+k ∀n∈Z,(u+np)2=u2+n2p2+2unp=(a+n2p+2un)p+k
所以: u 2 ≡ ( u + n p ) 2 ( m o d p ) u^2≡(u+np)^2(mod p) u2≡(u+np)2(modp)
那么由此可知我们只需要考虑 [ 0 , p − 1 ] [0,p-1] [0,p−1]范围内的 x 2 x^2 x2即可。
若存在两个不同的数 u , v ∈ [ 0 , p − 1 ] u,v\in[0,p-1] u,v∈[0,p−1],满足 u 2 ≡ v 2 ( m o d p ) u^2≡v^2(mod p) u2≡v2(modp),
显然有 u 2 − v 2 ≡ 0 ( m o d p ) u^2-v^2≡0(mod p) u2−v2≡0(modp)
由平方差公式可得 ( u + v ) ( u − v ) ≡ 0 ( m o d p ) (u+v)(u-v)≡0(mod p) (u+v)(u−v)≡0(modp),由 u u u, v v v的范围可知 ( u − v ) (u-v) (u−v)不可能满足,所以必满足 ( u + v ) ≡ 0 ( m o d p ) (u+v)≡0(mod p) (u+v)≡0(modp),即 u + v = p u+v=p u+v=p所以一共有 p − 1 2 \frac{p-1}{2} 2p−1个 u , v u,v u,v的值可以让方程有解。再加上 0 0 0的情况就是 p − 1 2 + 1 \frac{p-1}{2}+1 2p−1+1。
接下来引入勒让德符号:
( a p ) = { 1 a 是 模 p 意 义 下 的 二 次 剩 余 − 1 a 是 模 p 意 义 下 的 非 二 次 剩 余 0 a ≡ 0 ( m o d p ) (\frac{a}{p})=\left\{ \begin{array}{rcl} 1 & & a是模p意义下的二次剩余\\ -1 & & a是模p意义下的非二次剩余\\ 0 & & a≡0(mod p) \end{array} \right. (pa)=⎩⎨⎧1−10a是模p意义下的二次剩余a是模p意义下的非二次剩余a≡0(modp)
( a p ) = a p − 1 2 ( m o d p ) (\frac{a}{p})=a^{\frac{p-1}{2}}(modp) (pa)=a2p−1(modp)
证明:
当 a a a是模 p p p的二次剩余时,令 x 2 ≡ a ( m o d p ) x^2≡a(mod p) x2≡a(modp),
那么就有 x p − 1 ≡ 1 ( m o d p ) x^{p-1}≡1(mod p) xp−1≡1(modp),由费马小定理可知 x x x存在。
当 a a a是模 p p p的非二次剩余时,令 x 2 ≡ a ( m o d p ) x^2≡a(mod p) x2≡a(modp),
那么就有 x p − 1 ≡ 1 ( m o d p ) x^{p-1}≡1(mod p) xp−1≡1(modp),由费马小定理可知 x x x不存在。
当 a ≡ 0 ( m o d p ) a≡0(mod p) a≡0(modp)显然满足。
设 a a a满足 w = a 2 − n w=a^2-n w=a2−n是模 p p p的非二次剩余,即 x 2 ≡ w ( m o d p ) x^2≡w(mod p) x2≡w(modp)无解。
那么 x ≡ ( a + w ) p − 1 2 x≡(a+\sqrt{w})^{\frac{p-1}{2}} x≡(a+w)2p−1是二次同余方程 x 2 ≡ n ( m o d p ) x^2≡n(mod p) x2≡n(modp)的解。
证明:
给出一个式子 ( a + w ) p (a+\sqrt{w})^{p} (a+w)p将其二项式展开 ∑ i = 0 p C p r a p − r w r \sum_{i=0}^{p}C_p^ra^{p-r}\sqrt{w}^r ∑i=0pCprap−rwr,我们知道,当 p p p为奇素数时,若 i ≠ 0 , i ≠ p i \neq 0,i \neq p i=0,i=p,则有 C p i ≡ 0 ( m o d p ) C_p^i≡0(mod p) Cpi≡0(modp),所以该二项式除了第一项和最后一项,其余项模 p p p模 p p p都为 0 0 0,那么就有 ( a + w ) p ≡ a p + w ) p ( m o d p ) (a+\sqrt{w})^{p}≡a^p+\sqrt{w})^{p}(mod p) (a+w)p≡ap+w)p(modp),成立。由费马小定理可得 a p ≡ a p − 1 a ≡ a ( m o d p ) a^p≡a^{p-1}a≡a(mod p) ap≡ap−1a≡a(modp)。
因为 w p ≡ w p − 1 2 ( m o d p ) \sqrt{w}^{p}≡w^{\frac{p-1}{2}}(mod p) wp≡w2p−1(modp),根据我们之前给出的定理2,可知 w p − 1 2 = − 1 \sqrt{w}^{\frac{p-1}{2}}=-1 w2p−1=−1那么就有 a p + w p ≡ a − w ( m o d p ) a^p+\sqrt{w}^{p}≡a-\sqrt{w}(mod p) ap+wp≡a−w(modp)。
综述: ( a + w ) p ≡ a − w ( m o d p ) (a+\sqrt{w})^{p}≡a-\sqrt{w}(mod p) (a+w)p≡a−w(modp)。
可得:
( a + w ) p + 1 ≡ ( a + w ) p ( a + w ) (a+\sqrt{w})^{p+1}≡(a+\sqrt{w})^{p}(a+\sqrt{w}) (a+w)p+1≡(a+w)p(a+w)。
\quad \quad \quad \quad \quad ≡ ( a + w ) ( a + w ) ≡(a+\sqrt{w})(a+\sqrt{w}) ≡(a+w)(a+w)。
\quad \quad \quad \quad \quad ≡ a 2 − w ≡a^2-w ≡a2−w。
\quad \quad \quad \quad \quad ≡ n ( m o d p ) ≡n(modp) ≡n(modp)。
\quad 有了最后一个定理,我们就可以通过随机选择a的值来找到一个满足条件的解。之前的链接里有详细地解释为何可以随机取 a a a的值,总的来说就是找到正解所需的次数的期望只有 2 2 2。所以随机取 a a a的值可以很快地找到一个解,代码如下。
算法实现:因为大约有一半的数都是非二次剩余,所以可以随机一个 a a a,把 w \sqrt{w} w 当作一个复数单位,定义一个复数运算像这样:
int w,a;
struct cp
{
int x,y;
inline cp(R int _x,R int _y):x(_x),y(_y) {}
inline cp operator *(const cp &b)const
{
return cp(add(mul(x,b.x),mul(w,mul(y,b.y))),add(mul(x,b.y),mul(y,b.x)));
}
};
int ksm(R cp x,R int y)
{
R cp res(1,0);
for(; y; y>>=1,x=x*x)
if(y&1)
res=res*x;
return res.x;
}
int Sqrt(int x)
{
if(!x)
return 0;
if(ksm(x,(P-1)>>1)==P-1)
return -1;
while(true)
{
a=mul(rand(),rand()),w=dec(mul(a,a),x);
if(ksm(w,(P-1)>>1)==P-1)
return ksm(cp(a,1),(P+1)>>1);
}
}