【Timus1132】—Square Root(奇质数意义下的二次剩余)

传送门


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)=110a%pa%pa0(%p)

有结论(欧拉准则)
( a p ) ≡ a p − 1 2 (\frac{a}{p})\equiv a^{\frac{p-1}{2}} (pa)a2p1

证明

a ≡ 0 ( % p ) a\equiv0(\%p) a0(%p)时显然成立

由于费马小定理: a p − 1 ≡ 1 a^{p-1}\equiv 1 ap11
所以 a p − 1 2 ≡ 1   o r   − 1 ( % p ) a^{\frac{p-1}{2}}\equiv1\ {or}\ -1(\%p) a2p11 or 1(%p)

首先证明 ( a p ) = 1 (\frac{a}{p})=1 (pa)=1 a p − 1 2 = 1 a^{\frac{p-1}{2}}=1 a2p1=1

必要性:

由于 a ≡ x 2 , a\equiv x^2, ax2, 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) a2p1(x2)2p1xp11(%p)

充分性:

% p \%p %p意义下原根为 g g g,则 g k ≡ a p − 1 ≡ 1 ( % p ) g^k\equiv a^{p-1}\equiv 1(\%p) gkap11(%p)
则一定存在 g i ≡ a g^i\equiv a gia

g i ( p − 1 ) 2 = 1 g^{\frac{i(p-1)}{2}}=1 g2i(p1)=1
g p − 1 ≡ 1 g^{p-1}\equiv 1 gp11
所以 2 ∣ i 2|i 2i
所以必然存在 g i 2 ≡ x 0 ( % p ) g^{\frac{i}{2}}\equiv x_0(\%p) g2ix0(%p)

( a p ) = − 1 (\frac{a}{p})=-1 (pa)=1
反证可以得到 x p − 1 ≡ − 1 ( % p ) x^{p-1}\equiv -1(\%p) xp11(%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 wb2a且不存在二次剩余

由于 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 b2wax2
b 2 − w ≡ b 2 − i 2 ≡ ( b + i ) ( b − i ) b^2-w\equiv b^2-i^2\equiv (b+i)(b-i) b2wb2i2(b+i)(bi)

考虑 ( 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)bjipj
由于当 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)pbp+ipbp1b+w2p1i
由于 w w w % p \%p %p非二次剩余,所以 w p − 1 2 ≡ − 1 w^{\frac{p-1}{2}}\equiv -1 w2p11

所以 ( b + i ) p ≡ b − i (b+i)^p\equiv b-i (b+i)pbi
所以 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)(bi)(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
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
#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";
	}
}

你可能感兴趣的:(二次剩余)