數論之二次剩余


來自各個大佬的講解與證明:

二次剩余Cipolla算法學習筆記 - bztMinamoto - 博客園

[數論]二次剩余及計算方法 – Miskcoo's Space

淺談二次剩余 - stevensonson的博客 - CSDN博客

二次剩余入門 - Eiffel的博客 - CSDN博客

圖文]第4章二次同余方程 - 百度文庫

二次剩余Cipolla算法學習小記 - 待成熟的葡萄 - CSDN博客

 發現自己再回來看,忘了是怎么弄了,還是寫一下自己的體會,方便理解。

首先二次剩余是什么?也就是a∈Z,gcd(a,m)=1,如果x2Ξa(mod m)有解,那么a就是模m的二次剩余

當m小的時候,我們直接把0,1,2,..m/2代入計算就可以判斷有沒有解,而當m很大的時候,如果m是合數的時候比較難解決,所以我們就只來討論m是奇素數p的時候。

有個結論,歐拉判別條件

a是模p的二次剩余的充要條件是a(p-1)/2Ξ1(mod p) 

a是模p的非二次剩余的充要條件是a(p-1)/2Ξ-1(mod p) 

且a是p的二次剩余的時候,同余方程恰好有兩個解

證明是不會的,這輩子都不可能去證明了的。想看詳細證明的可以翻一翻上面的博客。

然后平方剩余的一些性質

若a1,a2都是模p的二次剩余,a1*a2也是模p的二次剩余

若a1,a2都是模p的非二次剩余,a1*a2是模p的二次剩余

若a1是模p的二次剩余,a2是模p的非二次剩余,a1*a2是模p的非二次剩余

接下來有一個概念:勒讓得符號(legender symbol)

根據上面的定義就有:

所以這3個描述是等價的

 

概念了解得差不多了,那怎么就是怎么求x2Ξa(mod m)的解x

就很霸道的一句話

設b滿足b2-a是模p的非二次剩余,設ω=√b2-a,那么x≡(b+ω)(p+1)/2是x2Ξa(mod m)的解

理解是話,按照設定w是模p不能開根號的,那我們非要給w開根號,那么它所在的值域就變了,我們假設一個域為Fp2,那這其實是一個類似復數域的存在,

所以這里理解的話ω,可以視為復數的那個虛部的i,Fp2域的數就可以表示為x+yω,且這個域是滿足其他域的性質,也可以四則運算。那么,x≡(b+ω)(p+1)/2也就是一個合法的數

然后為什么這就是同余方程的解呢。

用以下幾個定理來解釋

定理1.ωpΞ-ω (mod p)

證明:ωp=ω*ωp-1=ω*(ω2)(p-1)/2=ω*(b2-a)(p-1)/2=ω*-1 (mod p)

定理2.(a+b)n=an+bn (mod p)

證明:二項式展開就有,然后除了i=0以及i=n時,Cin=1,其余的mod n等於0

那么x≡(b+ω)(p+1)/2就有

x2≡(b+ω)p+1≡(b+ω)p*(b+ω) 

由第二個定理就有x2≡(bpp)*(b+ω) 

由費馬小定理bp-1≡1 (mod p)以及定理1有x2≡(b-ω)*(b+ω) 

最后 x2≡b22=b2-(b2-a)=a (mod p)

所以x≡(b+ω)(p+1)/2是x2Ξa(mod m)的解

剩下的為什么這個Fp2域的解是我們要求的解,我就不會證明了,可以看上面的最后那個博客,有提到,以及時間復雜度的分析。

然后在實際實現中,ω的作用就是在於(x1+y1ω)*(x2+y2ω) 時,類似實部的地方為x1*x2+y1*y2*ω2

所以直接可以讓ω為b2-a,b的話就是通過隨機數得到,這個期望值是2。

直接來一個裸題:http://acm.timus.ru/problem.aspx?space=1&num=1132

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<ctime>
 4 struct Ima{
 5     int x,y;
 6 };
 7 int p,w;
 8 Ima muli(const Ima &i1,const Ima &i2){
 9     Ima ans;
10     ans.x=(i1.x*i2.x%p+i1.y*i2.y%p*w%p)%p;
11     ans.y=(i1.x*i2.y%p+i1.y*i2.x%p)%p;
12     return ans;
13 }
14 Ima powi(Ima a,int b){
15     Ima ans;
16     ans.x=1,ans.y=0;
17     while(b){
18         if(b&1) ans=muli(ans,a);
19         a=muli(a,a);
20         b>>=1;
21     }
22     return ans;
23 }
24 int poww(int a,int b){
25     int ans=1;
26     a%=p;
27     while(b){
28         if(b&1) ans=ans*a%p;
29         a=a*a%p;
30         b>>=1;
31     }
32     return ans;
33 }
34 int Cipolla(int n){
35     if(p==2) return 1;
36     if(poww(n,(p-1)>>1)+1==p) return -1;
37     int a;
38     while(true){
39         a=rand()%p;
40         w=((a*a%p-n)%p+p)%p;
41         if(poww(w,(p-1)>>1)+1==p) break;
42     }
43     Ima ans;
44     ans.x=a,ans.y=1;
45     ans=powi(ans,(p+1)>>1);
46     return ans.x;
47 }
48 int main(){
49     int t,n,ans1,ans2;
50     srand(time(NULL));
51     scanf("%d",&t);
52     while(t--){
53         scanf("%d%d",&n,&p);
54         n%=p;
55         ans1=Cipolla(n),ans2=p-ans1;
56         if(ans1==-1) printf("No root\n");
57         else if(ans1==ans2) printf("%d\n",ans1);
58         else if(ans1<ans2) printf("%d %d\n",ans1,ans2);
59         else printf("%d %d\n",ans2,ans1); 
60     }
61     return 0;
62 }
tql

還有牛客多校的一題:Quadratic equation

Amy asks Mr. B  problem B. Please help Mr. B to solve the following problem.
Let p = 1000000007.
Given two integers b and c, please find two integers x and y (0≤x≤y<p) such that
(x+y) mod p=b
(x×y) mod p=c
由(x+y)%p=b,以及x跟y的取值范圍,我們可以知道x+y只有b或者是p+b兩個結果,然后(x-y)2=(x+y)2-4xy,而xy%p=c,所以可以得到(x-y)2≡b2-4c (mod p),把這個同余方程解出來就行了。
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<ctime>
 4 typedef long long ll;
 5 const ll p=1e9+7;
 6 struct Ima{
 7     ll x,y;
 8 };
 9 ll w;
10 Ima muli(const Ima &i1,const Ima &i2){
11     Ima ans;
12     ans.x=(i1.x*i2.x%p+i1.y*i2.y%p*w%p)%p;
13     ans.y=(i1.x*i2.y%p+i1.y*i2.x%p)%p;
14     return ans;
15 }
16 Ima powi(Ima a,ll b){
17     Ima ans;
18     ans.x=1,ans.y=0;
19     while(b){
20         if(b&1) ans=muli(ans,a);
21         a=muli(a,a);
22         b>>=1;
23     }
24     return ans;
25 }
26 ll poww(ll a,ll b){
27     ll ans=1;
28     a%=p;
29     while(b){
30         if(b&1) ans=ans*a%p;
31         a=a*a%p;
32         b>>=1;
33     }
34     return ans;
35 }
36 ll Cipolla(ll n){
37     if(n==0) return 0;
38     if(n==1) return 1;
39     if(poww(n,(p-1)>>1)+1==p) return -1;
40     ll a;
41     while(true){
42         a=rand()%p;
43         w=((a*a%p-n)%p+p)%p;
44         if(poww(w,(p-1)>>1)+1==p) break;
45     }
46     Ima ans;
47     ans.x=a,ans.y=1;
48     ans=powi(ans,(p+1)>>1);
49     return ans.x;
50 }
51 void solve(ll b,ll c){
52     ll n=((b*b%p-4*c%p)%p+p)%p;
53     ll a=Cipolla(n),x,y;
54     if(a==-1){
55         printf("-1 -1\n");
56         return ;
57     }
58     if(!((a+b)&1)) y=(a+b)/2,x=b-y; 
59     else y=(a+b+p)/2,x=b+p-y;
60     x=(x+p)%p;
61     y=(y+p)%p;
62     if(x>y) printf("%lld %lld\n",y,x);
63     else printf("%lld %lld\n",x,y);
64 }
65 int main(){
66     int t;
67     ll b,c; 
68     srand(time(NULL));
69     scanf("%d",&t);
70     while(t--){
71         scanf("%lld%lld",&b,&c);
72         solve(b,c);
73     }
74     return 0;
75 }
tqlll

然后補充一下關於勒讓得的一些性質

 

剩下的合數的還有其他補充內容就之后再更。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM