http://acm.timus.ru/problem.aspx?space=1&num=1132spa
題意:code
求 x^2 ≡ n mod p p是質數 的 解blog
本題中n>=1get
特判p=2,接下來求當p是奇素數時的解it
引理1:io
引理2:方程有解當且僅當class
定理:im
設a知足 不是模p的二次剩餘,db
即無解,img
那麼是二次剩餘方程的解
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; typedef long long LL; int w; struct T { int p,d; }; int mod(LL a,int p) { a%=p; if(a<0) a+=p; return a; } int Pow(int a,int b,int p) { int res=1; for(;b;a=1LL*a*a%p,b>>=1) if(b&1) res=1LL*res*a%p; return res; } //求勒讓德符號 int Legendre(int a,int p) { return Pow(a,p-1>>1,p); } //二次域上的乘法 T mul(T a,T b,int p) { T ans; ans.p=(1LL*a.p*b.p%p+1LL*a.d*b.d%p*w%p)%p; ans.d=(1LL*a.p*b.d%p+1LL*a.d*b.p%p)%p; return ans; } //二次域上的快速冪 T power(T a,int b,int p) { T ans; ans.p=1; ans.d=0; for(;b;a=mul(a,a,p),b>>=1) if(b&1) ans=mul(ans,a,p); return ans; } int solve(int n,int p) { if(p==2) return 1; if(Legendre(n,p)+1==p) return -1; int a; LL t; while(1) { a=rand()%p; t=1LL*a*a-n; w=mod(t,p); if(Legendre(w,p)+1==p) break; } T tmp; tmp.p=a; tmp.d=1; T ans=power(tmp,p+1>>1,p); return ans.p; } int main() { int t; scanf("%d",&t); int n,p; int a,b; while(t--) { scanf("%d%d",&n,&p); n%=p; a=solve(n,p); if(a==-1) { puts("No root"); continue; } b=p-a; if(a>b) swap(a,b); if(a==b) printf("%d\n",a); else printf("%d %d\n",a,b); } }