S o l u t i o n Solution Solution:
首先:
勒让德符号:
( a p ) = { 1 a 是 % p 意 义 下 的 二 次 剩 余 − 1 a 是 % p 意 义 下 的 非 二 次 剩 余 0 a ≡ 0 ( % p ) (\frac{a}{p})= \begin{cases} 1 & a是\%p意义下的二次剩余 \\ -1 & a是\%p意义下的非二次剩余\\ 0 & a\equiv 0(\%p)\\ \end{cases} (pa)=⎩⎪⎨⎪⎧1−10a是%p意义下的二次剩余a是%p意义下的非二次剩余a≡0(%p)
有结论(欧拉准则)
(
a
p
)
≡
a
p
−
1
2
(\frac{a}{p})\equiv a^{\frac{p-1}{2}}
(pa)≡a2p−1
证明
当 a ≡ 0 ( % p ) a\equiv0(\%p) a≡0(%p)时显然成立
由于费马小定理:
a
p
−
1
≡
1
a^{p-1}\equiv 1
ap−1≡1
所以
a
p
−
1
2
≡
1
o
r
−
1
(
%
p
)
a^{\frac{p-1}{2}}\equiv1\ {or}\ -1(\%p)
a2p−1≡1 or −1(%p)
首先证明 ( a p ) = 1 (\frac{a}{p})=1 (pa)=1时 a p − 1 2 = 1 a^{\frac{p-1}{2}}=1 a2p−1=1
必要性:
由于 a ≡ x 2 , a\equiv x^2, a≡x2, a p − 1 2 ≡ ( x 2 ) p − 1 2 ≡ x p − 1 ≡ 1 ( % p ) a^{\frac{p-1}{2}}\equiv(x^2)^{\frac{p-1}{2}}\equiv x^{p-1}\equiv 1(\%p) a2p−1≡(x2)2p−1≡xp−1≡1(%p)
充分性:
设
%
p
\%p
%p意义下原根为
g
g
g,则
g
k
≡
a
p
−
1
≡
1
(
%
p
)
g^k\equiv a^{p-1}\equiv 1(\%p)
gk≡ap−1≡1(%p)
则一定存在
g
i
≡
a
g^i\equiv a
gi≡a
则
g
i
(
p
−
1
)
2
=
1
g^{\frac{i(p-1)}{2}}=1
g2i(p−1)=1
又
g
p
−
1
≡
1
g^{p-1}\equiv 1
gp−1≡1
所以
2
∣
i
2|i
2∣i
所以必然存在
g
i
2
≡
x
0
(
%
p
)
g^{\frac{i}{2}}\equiv x_0(\%p)
g2i≡x0(%p)
(
a
p
)
=
−
1
(\frac{a}{p})=-1
(pa)=−1
反证可以得到
x
p
−
1
≡
−
1
(
%
p
)
x^{p-1}\equiv -1(\%p)
xp−1≡−1(%p),显然是不可能的
所以我们可以判断 k k k在 % p \%p %p意义下是否存在二次剩余
C i p o l l a Cipolla Cipolla算法
求解 p p p为奇质数的情况
随机一个数
b
b
b
使
w
≡
b
2
−
a
w\equiv b^2-a
w≡b2−a且不存在二次剩余
由于
w
w
w在
%
p
\%p
%p不存在二次剩余
可以类似虚数那样设
i
=
w
i=\sqrt w
i=w
由于
b
2
−
w
≡
a
≡
x
2
b^2-w\equiv a\equiv x^2
b2−w≡a≡x2
b
2
−
w
≡
b
2
−
i
2
≡
(
b
+
i
)
(
b
−
i
)
b^2-w\equiv b^2-i^2\equiv (b+i)(b-i)
b2−w≡b2−i2≡(b+i)(b−i)
考虑
(
b
+
i
)
p
=
∑
j
=
0
p
(
p
j
)
b
j
i
p
−
j
(b+i)^p=\sum_{j=0}^{p}{p\choose j}b^ji^{p-j}
(b+i)p=∑j=0p(jp)bjip−j
由于当
j
!
=
0
o
r
p
j!=0\ {or}\ p
j!=0 or p时,
(
p
j
)
≡
0
{p\choose j}\equiv 0
(jp)≡0
所以
(
b
+
i
)
p
≡
b
p
+
i
p
≡
b
p
−
1
b
+
w
p
−
1
2
i
(b+i)^p\equiv b^p+i^p\equiv b^{p-1}b+w^{\frac{p-1}{2}}i
(b+i)p≡bp+ip≡bp−1b+w2p−1i
由于
w
w
w是
%
p
\%p
%p非二次剩余,所以
w
p
−
1
2
≡
−
1
w^{\frac{p-1}{2}}\equiv -1
w2p−1≡−1
所以
(
b
+
i
)
p
≡
b
−
i
(b+i)^p\equiv b-i
(b+i)p≡b−i
所以
x
2
≡
(
b
+
i
)
(
b
−
i
)
≡
(
b
+
i
)
p
+
1
x^2\equiv (b+i)(b-i)\equiv (b+i)^{p+1}
x2≡(b+i)(b−i)≡(b+i)p+1
x
≡
(
b
+
i
)
p
+
1
2
x\equiv (b+i)^{\frac{p+1}{2}}
x≡(b+i)2p+1
由于
%
p
\%p
%p意义下非二次剩余不会少于
O
(
p
2
)
O(\frac p 2)
O(2p)个
所以期望找2次
b
b
b就存在
w
w
w是非二次剩余
复杂度 O ( l o g p ) O(log_p) O(logp)
#include<bits/stdc++.h>
using namespace std;
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
#define ll long long
#define cs const
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
int mod,w;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){
for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));return res;
}
struct plx{
int x,y;
plx(int _x=1,int _y=0):x(_x),y(_y){}
friend inline plx operator *(cs plx &a,cs plx &b){
return plx(add(mul(a.x,b.x),mul(mul(a.y,b.y),w)),add(mul(a.x,b.y),mul(a.y,b.x)));
}
};
inline plx ksm(plx a,int b){
plx res=plx();
for(;b;b>>=1,a=a*a)if(b&1)res=res*a;
return res;
}
inline int solve(int a){
if(mod==2)return 1;
if(ksm(a,(mod-1)/2)==mod-1)return -1;
int b;
while(1){
b=rand()%mod;
w=dec(mul(b,b),a);
if(ksm(w,(mod-1)/2)==mod-1)break;
}
return ksm(plx(b,1),(mod+1)/2).x;
}
int main(){
int T=read();
srand(time(NULL));
while(T--){
int a=read();mod=read();a%=mod;
a=solve(a);
if(a!=-1){
int b=mod-a;
if(a>b)swap(a,b);
if(a!=b)cout<<a<<" "<<b<<'\n';
else cout<<a<<'\n';
}
else cout<<"No root\n";
}
}