401
技術社區[雲棲]
URAL 1132 二次剩餘
1132. Square Root
Time limit: 1.0 second
Memory limit: 64 MB The number x is called a square root of a modulo n (root(a,n)) if x*x = a (mod n). Write the program to find the square
root of number a by given modulo n.
InputOne number K in the first line is an amount of tests (K ≤ 100000). Each next line represents separate test, which contains integers a and n (1 ≤ a, n ≤
32767, n is prime, a and n are relatively prime).
OutputFor each input test the program must evaluate all possible values root(a,n) in the range from 1 to n− 1 and output them in increasing order in one separate line using spaces.
If there is no square root for current test, the program must print in separate line: ‘No root’.
Sample
|
題意:x^2=a(mod n)(gcd(a,n)=1,n為素數)(有解x升序輸出,無解輸出"No root"(不包含雙引號))。
若是奇質數且
不能整除
,則:
-
是模
的二次剩餘當且僅當:
-
是模
的非二次剩餘當且僅當:
以勒讓德符號表示,即為:
費馬小定理是數論中的一個定理:假如a是一個整數,p是一個質數,那麼是p的倍數,可以表示為
如果a不是p的倍數,這個定理也可以寫成
-
- 當n不整除a,n為奇素數時,方程x^2=a(mod n)有解<==>a^((n-1)/2)=1(mod n),此時a稱之為n的二次剩餘類。相反無解<==>a^((n-1)/2)=-1(或者用n-1表示)(mod n)(歐拉準則),此時稱a為n的非二次剩餘類。
-
#include <iostream> #include <cstdio> #include <cstdlib> using namespace std; long long pow_mod(long long a,long long b,long long p) { long long res=1; while(b>0) { if(b&1)res=(res*a)%p; a=(a*a)%p; b>>=1; } return res; } long long solve(long long a,long long p) { long long q=p-1,s=0; while(q%2==0) { s++; q>>=1; } if(s==1)return pow_mod(a,(p+1)/4,p); long long z; while(1) { z = 1 + rand()%(p - 1); if(pow_mod(z, (p - 1)/2,p) != 1) break; } long long c = pow_mod(z, q , p); long long r = pow_mod(a, (q + 1)/2, p); long long t = pow_mod(a, q, p); long long m = s, b,i; while(1) { if(t%p==1)break; for(i=1; i<m; i++)if(pow_mod(t,1<<i,p)==1)break; b=pow_mod(c,1<<(m-i-1),p); r=(r*b)%p; c=(b*b)%p; t=(t*c)%p; m=i; } return r; } int main() { long long a,p,i; int t; scanf("%d",&t); while(t--) { scanf("%I64d%I64d",&a,&p); if(p==2) { if(a%p==1)printf("1\n"); else printf("No root\n"); continue; } if(pow_mod(a, (p-1)/2,p) != 1) { puts("No root"); continue; } i=solve(a,p); if(p-i==i)printf("%I64d\n",i); else printf("%I64d %I64d\n",min(i,p-i),max(i,p-i)); } return 0; }
最後更新:2017-04-03 15:22:09