二次剩余
对于素数 ppp 和数 aaa,满足 (a,p)=1(a,p)=1(a,p)=1。(注意 aaa 不一定小于 ppp)
若 ∃xx2≡a(modp)\exist_{x}\ x^2\equiv a\pmod p∃x x2≡a(modp),则称 aaa 是模 ppp 意义下的二次剩余,xxx 称为该二次剩余方程式的解。
否则称 aaa 是模 ppp 意义下的非二次剩余。
特判掉 p=2p=2p=2 的情况,接下来默认 ppp 均为非 222 质数,即奇素数。
勒让德符号
定义:
(ap)={0p∣a1a在(modp)意义下是二次剩余−1a在(modp)意义下不是二次剩余\Big(\frac{a}{p}\Big)= \begin{cases} 0\quad\quad\quad p\ \big|\ a\\ 1\quad\quad\quad a在\pmod p意义下是二次剩余\\ -1\quad\quad\ a在\pmod p意义下不是二次剩余 \end{cases} (pa)=⎩⎪⎨⎪⎧0p ∣∣ a1a在(modp)意义下是二次剩余−1 a在(modp)意义下不是二次剩余
欧拉准则
(ap)≡ap−12(modp)\Big(\frac ap\Big)\equiv a^{\frac{p-1}2}\pmod p (pa)≡a2p−1(modp)
证明:
-
p∣ap\ \big|\ ap ∣∣ a。显然成立。
-
当 aaa 是在模 ppp 意义下的二次剩余。
即 ∃xx2≡a(modp)\exist_x\ x^2\equiv a\pmod p∃x x2≡a(modp)。
有 (x2)p−12≡ap−12(modp)⇔xp−1≡ap−12(modp)(x^2)^\frac{p-1}2\equiv a^\frac{p-1}2\pmod p\Leftrightarrow x^{p-1}\equiv a^\frac{p-1}2\pmod p(x2)2p−1≡a2p−1(modp)⇔xp−1≡a2p−1(modp)。
∵(a,p)=1∴(x,p)=1\because (a,p)=1\therefore(x,p)=1∵(a,p)=1∴(x,p)=1。
⇒xp−1≡1≡ap−12(modp)\Rightarrow x^{p-1}\equiv 1\equiv a^\frac{p-1}2\pmod p⇒xp−1≡1≡a2p−1(modp)。
-
当 aaa 在模 ppp 意义下不是二次剩余。
则有 ∀i∈[1,p)ij≡a(modp)\forall_{i\in [1,p)}\ ij\equiv a\pmod p∀i∈[1,p) ij≡a(modp) 的 jjj 是唯一的,且 j≠ij\neq ij=i。
考虑用证明逆元唯一的思路来证明这里的唯一性。反证法。
假设 0<j1<j2<p0<j_1<j_2<p0<j1<j2<p 满足 ij1≡ij2≡a(modp)ij_1\equiv ij_2\equiv a\pmod pij1≡ij2≡a(modp)。
则 i(j2−j1)≡0(modp)⇒p∣i(j2−j1)i(j_2-j_1)\equiv 0\pmod p\Rightarrow p\ \big|\ i(j_2-j_1)i(j2−j1)≡0(modp)⇒p ∣∣ i(j2−j1)。
(i,p)=1⇒p∣(j2−j1)(i,p)=1\Rightarrow p\ \big|\ (j_2-j_1)(i,p)=1⇒p ∣∣ (j2−j1),与 0<j2−j1<p⇒(j2−j1,p)=10<j_2-j_1<p\Rightarrow (j_2-j_1,p)=10<j2−j1<p⇒(j2−j1,p)=1 矛盾。
p−1p-1p−1 是偶数,那么我们考虑可以把这些数两两配对,配出 p−12\frac{p-1}22p−1 对。
即 ap−12≡(p−1)!≡−1(modp)a^\frac{p-1}2\equiv (p-1)!\equiv -1\pmod pa2p−1≡(p−1)!≡−1(modp)(威尔逊定理)。
换言之:
x2≡a(modp),(a,p)=1x^2\equiv a\pmod p,(a,p)=1x2≡a(modp),(a,p)=1。
ap−12≡±1(modp)a^\frac{p-1}2\equiv \pm 1\pmod pa2p−1≡±1(modp)。
方程有解当且仅当 ap−12≡1(modp)a^\frac{p-1}{2}\equiv 1\pmod pa2p−1≡1(modp)。
Cipolla
lemma
:设 ω\omegaω 不是模 ppp 的二次剩余,即 ̸∃xx2≡ω(modp)\not\exist_x\ x^2\equiv \omega\pmod p∃x x2≡ω(modp),且 ω=t2−a\omega=t^2-aω=t2−a。则 x=(t+ω)p+12x=(t+\sqrt{\omega})^\frac{p+1}2x=(t+ω)2p+1 是二次剩余方程 x2≡a(modp)x^2\equiv a\pmod px2≡a(modp) 的解。
证明:
(t+ω)p=∑i=0p(pi)ti(ω)p−i=tp+ωp2+∑i=1p−1(pi)ti(ω)p−i(t+\sqrt\omega)^p=\sum_{i=0}^{p}\binom pit^i(\sqrt\omega)^{p-i}=t^p+\omega^\frac{p}2+\sum_{i=1}^{p-1}\binom pit^i(\sqrt\omega)^{p-i}(t+ω)p=∑i=0p(ip)ti(ω)p−i=tp+ω2p+∑i=1p−1(ip)ti(ω)p−i。
i∈(0,p),(pi)=p!i!(p−i)!i\in(0,p),\binom{p}{i}=\frac{p!}{i!(p-i)!}i∈(0,p),(ip)=i!(p−i)!p!。
组合数是整数,i!,(p−i)!i!,(p-i)!i!,(p−i)! 里的每个数都 <p<p<p,又 ppp 是奇素数,所以 i!,(p−i)!i!,(p-i)!i!,(p−i)! 里面均不会筛到 ppp。
所以 p∣(pi)p\ \big|\ \binom pip ∣∣ (ip)。也就是说后面的求和在模 ppp 意义下是 000。
⇒(t+ω)p≡tp+(ω)p(modp)\Rightarrow (t+\sqrt\omega)^p\equiv t^p+(\sqrt\omega)^p\pmod p⇒(t+ω)p≡tp+(ω)p(modp)。
tp+(ω)p=tp+ωp−12ωt^p+(\sqrt\omega)^p=t^p+\omega^\frac{p-1}2\sqrt\omegatp+(ω)p=tp+ω2p−1ω,因为 ω\omegaω 不是模 ppp 意义下的二次剩余,所以 (ωp)=−1=ωp−12\Big(\frac \omega p\Big)=-1=\omega^\frac{p-1}2(pω)=−1=ω2p−1,tp=tp−1t≡t(modp)t^p=t^{p-1}t\equiv t\pmod ptp=tp−1t≡t(modp)。
⇒(t+ω)p≡t−ω(modp)\Rightarrow (t+\sqrt\omega)^p\equiv t-\sqrt\omega\pmod p⇒(t+ω)p≡t−ω(modp)
x2≡(t+ω)p+1≡(t+ω)p(t+ω)≡(t−ω)(t+ω)≡t2−ω≡a(modp)x^2\equiv (t+\sqrt\omega)^{p+1}\equiv(t+\sqrt\omega)^p(t+\sqrt\omega)\equiv(t-\sqrt\omega)(t+\sqrt\omega)\equiv t^2-\omega\equiv a\pmod px2≡(t+ω)p+1≡(t+ω)p(t+ω)≡(t−ω)(t+ω)≡t2−ω≡a(modp)。
在算法实现中,随机 ttt 后求 ω\omegaω,大约有一半的数都是非二次剩余。期望两次便可求出 xxx。
考虑另一种二次剩余方程:x2≡a(modpn)x^2\equiv a\pmod {p^n}x2≡a(modpn),其中 (a,p)=1(a,p)=1(a,p)=1,ppp 为奇质数。
先求出 x2≡a(modp)x^2\equiv a\pmod px2≡a(modp) 的一个解 τ\tauτ,有 τ2−a=kp⇒(τ2−a)n≡knpn≡0(modpn)\tau^2-a=kp\Rightarrow (\tau^2-a)^n\equiv k^np^n\equiv 0\pmod {p^n}τ2−a=kp⇒(τ2−a)n≡knpn≡0(modpn)。
{(r+a)n=f+ga(r−a)n=f−ga\begin{cases}(r+\sqrt a)^n=f+g\sqrt{a}\\(r-\sqrt a)^n=f-g\sqrt{a}\end{cases}{(r+a)n=f+ga(r−a)n=f−ga
两个式子的结果答案长相一定可以这么写。
证明:二项式定理展开 (ni)τn−i(±a)i\binom ni\tau^{n-i}(\pm\sqrt{a})^i(in)τn−i(±a)i,(±a)i(\pm\sqrt{a})^i(±a)i 如果 iii 是偶数,第 iii 项就在 fff 里面,否则就在 ggg 里面。
也就是说,(τ2−a)n≡[(τ+a)(τ−a)]n≡(τ+a)n(τ−a)n≡(f+ga)(f−ga)≡f2−g2a≡0(modpn)(\tau^2-a)^n\equiv [(\tau+a)(\tau-a)]^n\equiv(\tau+a)^n(\tau-a)^n\equiv(f+g\sqrt{a})(f-g\sqrt{a})\equiv f^2-g^2a\equiv 0\pmod {p^n}(τ2−a)n≡[(τ+a)(τ−a)]n≡(τ+a)n(τ−a)n≡(f+ga)(f−ga)≡f2−g2a≡0(modpn)。
(f,p)=1,(g,p)=1⇒f2inv(g2)≡a(modn)(f,p)=1,(g,p)=1\Rightarrow f^2\text{inv}(g^2)\equiv a\pmod n(f,p)=1,(g,p)=1⇒f2inv(g2)≡a(modn)。
由于 pnp^npn 不是质数,所以用 exgcd\text{exgcd}exgcd 求逆元即可。
代码
#include <cstdio>
#include <iostream>
#include <ctime>
#include <random>
using namespace std;
#define int long long
int T, n, p, omega;
mt19937 wwl(time(0));struct complex {int x, y;complex(){}complex( int X, int Y ) { x = X, y = Y; }complex operator * ( complex v ) {int ansx = ( x * v.x % p + y * v.y % p * omega % p ) % p;int ansy = ( x * v.y % p + y * v.x % p ) % p;return complex( ansx, ansy );}
};int qkpow( complex x, int y ) {complex ans( 1, 0 );while( y ) {if( y & 1 ) ans = ans * x;x = x * x;y >>= 1;}return ans.x;
}int qkpow( int x, int y, int mod ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}int cipolla( int n, int p ) {n %= p;if( p == 2 ) return n;if( qkpow( n, p - 1 >> 1, p ) == p - 1 ) return -1;int t;while( 1 ) {t = wwl() % p;omega = ( ( t * t % p - n ) % p + p ) % p;if( qkpow( omega, p - 1 >> 1, p ) == p - 1 ) break;}complex ans( t, 1 );return qkpow( ans, p + 1 >> 1 );
}signed main() {scanf( "%lld", &T );while( T -- ) {scanf( "%lld %lld", &n, &p );if( n == 0 ) { puts("0"); continue; }int ans = cipolla( n, p );if( ! ~ ans ) { puts("Hola!"); continue; }if( ans == p - ans ) printf( "%lld\n", ans );else printf( "%lld %lld\n", min( ans, p - ans ), max( ans, p - ans ) );}return 0;
}