【Timus1132】—Square Root(奇质数意义下的二次剩余)
:
首先:
勒让德符号:
有结论(欧拉准则)
证明
当时显然成立
由于费马小定理:
所以
首先证明时
必要性:
由于
充分性:
设意义下原根为,则
则一定存在
则
又
所以
所以必然存在
反证可以得到,显然是不可能的
所以我们可以判断在意义下是否存在二次剩余
算法
求解为奇质数的情况
随机一个数
使且不存在二次剩余
由于在不存在二次剩余
可以类似虚数那样设
由于
考虑
由于当时,
所以
由于是非二次剩余,所以
所以
所以
由于意义下非二次剩余不会少于个
所以期望找2次就存在是非二次剩余
复杂度
#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";
}
}