1. 程式人生 > 其它 >2020版本IDEA破解教程,輕鬆破解到2099年

2020版本IDEA破解教程,輕鬆破解到2099年

學了一下最基本的二次剩餘

很早就聽說過二次剩餘的概念了,但由於沒有一直碰到過相關的題目加上學不太明白,所以一直拖啊拖沒去認真學,最近終於碰到了要用到二次剩餘相關知識的題,然後滾去認真學習了一波,現寫篇部落格記錄下所學所想。不然過幾天又忘了

二次剩餘在數論的研究和實際上好像有很廣泛的運用,但在演算法競賽中用的不多,一般是用來求解二次同餘式俗稱模意義開根 \(or\)​​​​ 判斷一些有關多次同餘式的解的存在性問題。

考慮到高次剩餘和模數 \(p\)​​​​ 為合數的情況比較少見我不會,這裡就不多加討論,我們只討論 \(p\)​​​ 為奇素數和 \(n\neq0\)​​​ 的情況,\(p=1、p=2、n=0\)​​​ 的情況顯然很好特判。

為了方便描述,我們約定,以下運算都是在模 \(p\)​​​​​​ 意義下進行的,即同餘符號 \(\equiv\)​​​ 都省略了後面的 \({\rm mod}\ p\)​​​,且 \(n,x\in[1,p-1]\)​​​​​。

定義

給定一個正整數 \(p\)​​​​​,若對於一個正整數 \(n\)​​​​,存在整數 \(x\)​​​ 滿足 \(x^2\equiv n\pmod p\)​​​,則稱 \(n\)​​​ 是模 \(p\)​​​ 的二次剩餘,否則稱 \(n\)​​​ 為模 \(p\)​​​ 的二次非剩餘(或者說非二次剩餘)。

例如 \(4^2\equiv 1\pmod 5\),因此 \(1\)

是模 \(5\) 的二次剩餘。

性質

性質 1​​​:\(p\)​ 意義下的二次剩餘 \(n\)​ 一共有 \(\displaystyle\frac{p-1}2\)​ 個(不包括 \(0\)​​)。

證明:

直接討論 \(n\)​​​​​​ 的數量的話感覺沒啥頭緒,但注意到這裡的每個 \(n\)​​​​​​ 都對應著一個 \(x^2\)​​​​​​,我們可以來試試討論 \(x^2\)​​​​​​。
顯然有 \(x^2\equiv(-x)^2\)​​​​​​,而在模 \(p\)​​​​​​ 意義下,\(-x\iff p-x\)​​​​​​,因此只需討論 \(x\in[1,\displaystyle\frac{p-1}2]\)

​​​​​​,便可覆蓋到所有可能的 \(n\),既然只有 \(\displaystyle\frac{p-1}2\) 個不同的 \(x\),那麼顯然最多隻有 \(\displaystyle\frac{p-1}2\) 個對應的 \(n\),接下來我們只需證明這些 \(x\) 的平方模 \(p\) 兩兩不相等,即可得證。
證明這種取模兩兩不相等的套路一般都是反證法,可以參考這篇部落格對於完全剩餘系的性質的證明。
假設存在不同的兩個數 \(x,y\in[1,\displaystyle\frac{p-1}2]\)\(x^2\equiv y^2\),則有 \((x+y)(x-y)\equiv 0\),顯然根據 \(x,y\) 的取值範圍,有 \(-p<x+y<p,\ -p<x-y<p,\ x+y\neq0,\ x-y\neq0\),即 \((x+y)(x-y)\) 不可能模 \(p\)\(0\)​​,故假設不成立,原命題得證。

性質 2​​​​:兩個二次剩餘相乘、或者兩個二次非剩餘相乘,得到的仍是一個二次剩餘。

性質 3​:一個二次剩餘和一個二次非剩餘相乘,得到的是一個二次非剩餘。

性質 4:一個二次剩餘的逆元也是二次剩餘。

性質 2、3、4 都可由尤拉準則輕鬆證出,故此處證明略。

勒讓德符號(Legendre Symbol)

為了方便描述,我們定義勒讓德符號 \(\left(\displaystyle\frac np\right)\)​​​​​,它滿足:

\[\left(\frac np\right)=\begin{cases} 1\qquad \text{n 是模 p 的二次剩餘}\\ -1\quad\ \text{n 是模 p 的二次非剩餘}\\ 0\qquad \text{n 是0} \end{cases} \]

尤拉準則

當你要判斷一個數 \(n\)​​ 是不是模 \(p\)​ 的二次剩餘時,有:\(n\) 是模 \(p\) 的二次剩餘,當且僅當 \(n^{\frac {p-1}2}\equiv 1\)​​​​​​​​​ 。

證明:

充分性:當 \(n\) 是二次剩餘時,根據費馬小定理,我們有 \(n^{\frac{p-1}2}\equiv (x^2)^{\frac{p-1}2}\equiv x^{p-1}\equiv1\),充分性得證。
必要性:假設 \(g\) 為模 \(p\) 的一個原根,則一定有某個正整數 \(k\) 滿足 \(g^k\equiv n\),我們只需要取 \(x=g^{\frac k2}\),即可使得 \(x^2\equiv n\),接下來只需要證明 \(k\) 是偶數即可。
\(n^{\frac {p-1}2}\equiv 1\) 時,我們有 \(n^{\frac{p-1}2}\equiv (g^k)^\frac{p-1}2\equiv 1\),因為 \(g\) 是一個原根,所以當 \((g^k)^\frac{p-1}2\equiv 1\) 時一定有 \(p-1\mid k*\frac{p-1}2\),因此 \(k/2\) 一定是個整數,即 \(k\) 一定是偶數。
也就是說,當 \(n^{\frac {p-1}2}\equiv 1\) 時,一定存在某個數 \(x\) 使得 \(x^2\equiv n\),即 \(n\) 是一個二次剩餘,必要性得證。

同時由於 \(n^{\frac {p-1}2}\)​​ 不是 \(1\)​​ 就是 \(-1\)​​、\(n\)​​ 不是二次剩餘就是二次非剩餘,所以 \(n\)​​ 是二次非剩餘和 \(n^{\frac {p-1}2}\equiv -1\)​​ 也是等價的,發現這剛好符合我們上面對勒讓德符號的定義,因此又有 \(n^{\frac {p-1}2}\equiv\left(\dfrac np\right)\)​​​。

有了尤拉準則,上面的性質 \(2\)​​ 和性質 \(3\)​​ 也非常好證了,這裡簡單地證明一下性質 \(3\)​:

證明:\(n_1\)​ 是二次剩餘,\(n_2\)​ 是二次非剩餘,則有 \((\frac {n_1}p)\equiv1,\ (\frac{n_2}p)\equiv-1\iff n_1^{\frac{p-1}2}\equiv1,\ n_2^{\frac{p-1}2}\equiv-1\)​,那麼 \((n_1*n_2)^{\frac{p-1}2}\equiv n_1^{{\frac{p-1}2}}*n_2^{\frac{p-1}2}\equiv -1\)​,即 \(n1*n2\)​ 是一個二次非剩餘,得證。

Cipolla 演算法

可以在 \(O(\log p)\)​​​​ 的時間內求解二次同餘方程 \(x^2\equiv n\pmod p\)​​​​​。感覺有點玄學,涉及到複數域的推廣,並沒有理解的很明白,但總之先記錄下來吧。

演算法思路

1、找到一個數 \(a\) 滿足 \(a^2-n\) 是二次非剩餘​​​​。

2、定義 \(i^2\equiv a^2-n\)​​​​​​​​​,由於 \(a^2-n\)​​​​​​​ 是二次非剩餘,顯然這樣的 \(i\)​​​​​​​​ 並不存在,但我們可以像實數推廣到複數域一樣,把模 \(p\)​​​ 的實數域擴張為複數域,用 \(A+Bi\)​​​ 來表示這個域中的所有數(虛數單位 \(i=\sqrt{a^2-n}\)),\(A,B\) 都是模 \(p\)​​​​​ 意義下的數。

3、則有 \((a+i)^{p+1}\equiv n\),解 \(x\) 即為 \((a+i)^{\frac{p+1}2}\)​​​​。

正確性證明

引理 1​:\(i^p\equiv-i\)

證明:\(i^p\equiv i*(i^2)^{\frac{p-1}2}\equiv i*(a^2-n)^{\frac{p-1}{2}}\equiv-i\)

引理 2:\((a+b)^p\equiv a^p+b^p\)

證明:二項式定理展開後,共有 \(p+1\)​​​​​​​​ 項,每一項都是 \({\rm C}_p^ma^mb^{p-m},~m\in[0,p]\)​​​ 的形式​,因為 \(p\)​​​ 為質數,所以除了 \(m=0\)​​​ 和 \(m=p\)​​​ 的兩項,其他項的 \({\rm C}_p^m\)​​​ 的分子都會有一個 \(p\)​​ 約不掉,這些項模 \(p\)​ 都為 \(0\)​,因此最後只剩下兩項:\(a^p+b^p\) ,得證。

於是我們有:

\[\begin{aligned} (a+i)^{p+1}&\equiv(a+i)^p(a+i) \\ &\equiv (a^p+i^p)(a+i) \\ &\equiv (a^p-i)(a+i) \\ &\equiv (a-i)(a+i) \\ &\equiv a^2-i^2 \\ &\equiv n \end{aligned} \]

\((a+i)^{\frac {p+1}2}\)​​​​ 為方程的解 \(x\)​​​​​,其相反數是另一個解。

但這是拓展了數域的條件下所求得的答案,這個答案在原數域下也成立嗎?顯然如果要使答案在原數域下也成立,所求得的數的虛部就必須為 \(0\)​​​​,接下來證明 \((a+i)^{\frac {p+1}2}\)​ 的虛部一定為 \(0\)​。

證明:

反證法,假設 \((a+i)^{\frac {p+1}2}\equiv A+Bi\)​​,且 \(B\neq0\)​​。
那麼我們有 \((A+Bi)^2\equiv A^2+2ABi+B^2i^2\equiv n\)​​,移項並把 \(i^2=a^2-n\)​​ 代入得 \(A^2+B^2(a^2-n)-n\equiv-2ABi\)​​。
同餘式左邊是常數,右邊肯定也是常數,所以 \(AB\equiv 0\)​​,同時因為 \(B\neq0\)​​,則 \(A\equiv 0\)​​,從而有 \((Bi)^2\equiv n\iff i^2\equiv nB^{-2 }\)​​​,因為 \(n\)​​​ 是二次剩餘,\(B^2\)​​ 是二次剩餘,所以 \(nB^{-2}\)​ 也是二次剩餘,這與 \(i^2\)​ 是二次非剩餘矛盾,所以 \(B\) 一定為 \(0\),得證。​

時間複雜度分析

如何找到這樣的 \(a\)​​​ 滿足 \(a^2-n\)​​​ 是二次非剩餘?很簡單,我們只需隨機生成一個數 \(a\)​​​,然後用尤拉準則判斷 \(a^2-n\)​​​ 是否為二次非剩餘即可,因為二次剩餘的和二次非剩餘的數量都為 \(\dfrac {p-1}2\)​​​,所以整數域裡的某個數是二次非剩餘的概率約為 \(50\%\)​​​,因此隨機的期望次數是 \(2\)​​ 次,每次都用尤拉準則 \(O(\log p)\)​​ 判斷一下,時間複雜度是 \(O(\log p)\)​​​。找到了 \(a\) 以後,只需用複數域上的快速冪即可求出解,時間複雜度 \(O(\log p)\),總時間複雜度 \(O(\log p)\)​。

程式碼實現

模板題看這裡。

Code
#include<bits/stdc++.h>
using namespace std;
long long n,p;
long long i;
struct td{	//自定義的複數
	long long x,y;
	td(long long xx=0,long long yy=0){
		x=xx,y=yy;
	}
	td operator * (td a){	//等價於複數相乘
		return td( (x*a.x+i*y%p*a.y)%p,	
		(y*a.x+x*a.y)%p);
	}
};
long long qsm(long long a,long long b){
	long long ret=1;
	while(b){
		if(b&1) ret*=a,ret%=p;
		b>>=1,a*=a,a%=p;
	} return ret;
}
td t_qsm(td a,long long b){
	td ret(1,0);
	while(b){
		if(b&1){
			ret=ret*a;
		}
		b>>=1,a=a*a;
	} return ret;
}
bool legendre(long long n){ return qsm(n,(p-1)/2)==1; } 
int main(){
	int t; cin >> t;
	mt19937 mt_rand(time(0));	//隨機性更好一些的隨機
	while(t--){
		cin >> n >> p;
		if(n==0){	//特判0
			cout <<"0\n";
			continue;
		}
		if(legendre(n)){
			long long a=mt_rand()%p;	
			while(legendre(a*a-n)){	
				a=mt_rand()%p;
			}
			i=(a*a+p-n)%p;		//相當於複數的單位根
			td ans=t_qsm(td(a,1),(p+1)/2);	//答案即為 (a,1)^{(p+1)/2}
			ans.x=min(ans.x,p-ans.x);	//顯然有兩個答案 (x)^2 ≡ (p-x)^2 
			cout << ans.x << " " << p-ans.x << endl;
		}
		else cout << "Hola!\n";
	}
}

參考資料

  1. 二次剩餘 - OI Wiki (oi-wiki.org)
  2. https://www.luogu.com.cn/blog/zhang-xu-jia/qian-tan-er-ci-sheng-yu
  3. https://www.luogu.com.cn/blog/Vectory/er-ci-sheng-yu
  4. https://blog.csdn.net/acdreamers/article/details/10182281
  5. https://blog.csdn.net/Estia_/article/details/88789451
  6. https://baike.baidu.com/item/%E4%BA%8C%E6%AC%A1%E5%89%A9%E4%BD%99/3990744?fr=aladdin
  7. https://kewth.github.io/2019/10/21/%E4%BA%8C%E6%AC%A1%E5%89%A9%E4%BD%99/