1. 程式人生 > 實用技巧 >數論總結

數論總結

素數

素數

定義

  • 素數(prime number)又稱質數,有無限個。

    素數定義為在大於1的自然數中,除了1和它本身外不再有其他的因數,否則稱為合數。

性質

  • 任何一個大於1的自然數都可以分解成幾個素數連乘積的形式,而且這種分解是唯一的。
    大於1且第一個能被該自然數整除的數肯定是該分解中最小的素因子(唯一分解定理)。

  • 兩個質數一定是互質數。例如,271319

  • 一個質數如果不能整除另一個合數,這兩個數為互質數。例如,310526

  • 1不是質數也不是合數,它和任何一個自然數在一起都是互質數。如19908

  • 相鄰的兩個自然數是互質數。如1516

  • 相鄰的兩個奇數是互質數。如49

    51

  • 2和任意奇數互質

code

O(\(\sqrt n\))求單個素數

bool isPrime(int x) { 
	if (x < 2) return false; 
	for (int i = int(sqrt(x+0.5)); i >= 2; --i) {
		if (x % i == 0) 
		return false; 
	} 
	return true; 
} 

\(O(n)\)線性篩求\(1-n\)之間的素數

int prime[MAXN]; // 儲存素數
bool is_not_prime[MAXN] = {1, 1}; // 0和1都不是素數
// 篩選 n 以內的所有素數
void judge_prime(int n) {
	for (int i = 2; i <= n; ++i) {
		if (!is_not_prime[i]) { // 如果i是素數
			prime[++prime[0]] = i;
		}
		for (int j = 1; j <= prime[0] && i * prime[j] <= n; ++j) {
			is_not_prime[i*prime[j]] = 1;
			// 如果i中包含了該質因子,則停止
			if (i % prime[j] == 0) break;
		}
	}
}

尤拉函式

尤拉

萊昂哈德·尤拉(Leonhard Euler ,1707年4月15日~1783年9月18日),瑞士數學家、自然科學家。1707年4月15日出生於瑞士的巴塞爾,1783年9月18日於俄國聖彼得堡去世。歐拉出生於牧師家庭,自幼受父親的影響。13歲時入讀巴塞爾大學,15歲大學畢業,16歲獲得碩士學位。尤拉是18世紀數學界最傑出的人物之一,他不但為數學界作出貢獻,更把整個數學推至物理的領域。他是數學史上最多產的數學家,平均每年寫出八百多頁的論文,還寫了大量的力學、分析學、幾何學、變分法等的課本,《無窮小分析引論》、《微分學原理》、《積分學原理》等都成為數學界中的經典著作。尤拉對數學的研究如此之廣泛,因此在許多數學的分支中也可經常見到以他的名字命名的重要常數、公式和定理。 此外尤拉還涉及建築學、彈道學、航海學等領域。瑞士教育與研究國務祕書Charles Kleiber曾表示:“沒有尤拉的眾多科學發現,我們將過著完全不一樣的生活。”法國數學家拉普拉斯則認為:讀讀尤拉,他是所有人的老師。2007年,為慶祝尤拉誕辰300週年,瑞士政府、中國科學院及中國教育部於2007年4月23日下午在北京的中國科學院文獻情報中心共同舉辦紀念活動,回顧尤拉的生平、工作以及對現代生活的影響。
——From 百度百科

定義

數論,對正整數n,尤拉函式是小於或等於n的正整數中與n互質的數的數目(因此\varphi(1)=1)。此函式以其首名研究者尤拉命名(Euler's totient function),它又稱為Euler's totient function、\varphi函式、尤拉商數等。 例如\varphi(8)=4,因為1,3,5,7均和8互質。 從尤拉函式引伸出來在環論方面的事實和拉格朗日定理構成了尤拉定理的證明。
——From 百度百科

性質

  • \(\varphi(1)=1\)(和1互質的數(小於等於1)就是1本身)。注意:每種質因數只有一個。

  • 若n是質數p的k次冪,\(\varphi(n)=p^k - p^{k-1}=(p-1)p^{k-1}\),因為除了p的倍數外,其他數都跟n互質。

  • 尤拉函式是積性函式——若m,n互質\(\varphi(mn)=\varphi(m)\varphi(n)\)

  • 當n為奇質數時,\(\varphi(2n)=\varphi(n)\)

  • p為素數,若 \(n%p=0\),則\(\varphi(n×p)=\varphi(n)×p\)

  • p為素數,若 \(n%p≠0\),則\(\varphi(n×p)=\varphi(n)×(p−1)\)

  • 與n互質的數都是成對出現的,且每對的和為\(n\),所以大於2的數的\(\varphi(n)\)都為偶數。

最大公因數

最大公因數

定義

  • 一組數的公約數,是指同時是這組數中每一個數的約數的數。而最大公約數,則是指所有公約數裡面最
    大的一個,常縮寫為 gcd(Greatest Common Divisor)。 求 gcd 常用的方法為輾轉相除法(歐幾里得演算法),還有一種為更相減損法。、

求解

code1

  • 輾轉相除法(歐幾里得法)求兩個數的最大公因數
int get_gcd(int x,int y){
	if(y==0) return x;
	return getgcd(y,x%y); 
} 

code2

  • 輾轉相減法(尼考曼徹斯法)求兩個數的最大公因數
  • 如果寫高精度的話,用這一種會比較方便。
int getgcd(int x,int y){
	return x==y ? x : getgcd(x > y ? x - y : x , y > x ? y-x : y); 
} 

code3

  • 求兩個數的最小公倍數,\(lcm(aa,bb)=aa×bb÷gcd(aa,bb)\)

code4

  • 求多個數的最大公因數或最小公倍數,兩兩相求就可以了

擴充套件歐幾里得定理

歐幾里得

歐幾里得(英文:Euclid;希臘文:Ευκλειδης ,約公元前330年—公元前275年),古希臘人,數學家,被稱為“幾何之父”。他最著名的著作《幾何原本》是歐洲數學的基礎,提出五大公設,歐幾里得幾何,被廣泛的認為是歷史上最成功的教科書。歐幾里得也寫了一些關於透視、圓錐曲線、球面幾何學及數論的作品。
——From 百度百科

定義

  • 對於不完全為 0 的整數 a,b,\(gcd(a,b)\)表示 \(a,b\) 的最大公約數。那麼一定存在整數 \(x,y\) 使得 \(gcd(a,b)=ax+by\)

code1

int exgcd(int aa,int bb,int &x,int &y){
    if(bb==0){
        x=1,y=0;
        return aa;
    }
    int ans=exgccd(bb,aa%bb,x,y);
    int t=x;
    x=y;
    y=t-aa/bb*y;
    return ans;
}

code2

費馬小定理 & 尤拉定理

費馬小定理

費馬

皮埃爾·德·費馬,法國律師和業餘數學家。他在數學上的成就不比職業數學家差,他似乎對數論最有興趣,亦對現代微積分的建立有所貢獻。被譽為“業餘數學家之王”。費馬,是當今常見譯法,80年代的書籍文章也多見譯為“費爾瑪”的情況,但“費瑪”則少見。 ——From 百度百科

定義

  • 如果\(p\)是一個質數,而整數\(a\)不是\(p\)的倍數,則有\(a^{p−1}\equiv 1(\mod p)\)

  • 另一個形式:若\(p\)為素數,對於任意整數 \(a\),有\(a^p \equiv a(\mod p)\)

尤拉定理

  • 費馬小定理是用來闡述在素數模下,指數的同餘性質。當模是合數的時,就要應用範圍更廣的尤拉定理了。

定義

  • 在數論中,尤拉定理,(也稱費馬-尤拉定理)是一個關於同餘的性質。尤拉定理表明,若\(n,a\)為正整數,且\(n,a\)互質,則:\(a^{\varphi(n)}\equiv1(\mod p)\)

  • 其實,當m為素數時,與費馬小定理相同

拓展尤拉定理

乘法逆元

乘法逆元

  • \((a×x)\equiv 1(\mod b)\),則稱 \(x\)\(a\)在模 \(b\)意義下的乘法逆元,記為 \(a−1\)
    注意:並非所有的情況下都存在乘法逆元,但是當 \(gcd(a,b)=1\)\(a,b\)互質時,存在乘法逆元。

求解

費馬小定理求逆元

typedef long long ll;
ll quickpow(ll a, ll n, ll p) { //快速冪求 a^n % p
	ll ans = 1;
	while(n) {
		if(n & 1) ans = ans * a % p;
		a = a * a % p;
		n >>= 1;
	}
	return ans;
}
ll niyuan(ll a, ll p) { //費馬小定理求逆元 a^(p-2)%p
	return quickpow(a, p - 2, p);
}
  • 注意:該方法的前提條件:模數為素數,且 a不是p的倍數。

歐幾里得求逆元

// ax+by=1
int exgcd(int a, int b, int &x, int &y) {
	if (b == 0) {
		x = 1;
		y = 0;
		return b; // b為最大公約數
	}
	// 注意傳參及下面的計算
	int ret = exgcd(b, a%b, y, x);
	y -= a/b*x;
	return ret;
}
// ax+by=1
int exgcd2(int a, int b, int &x, int &y) {
	if (b == 0) {
		x = 1;
		y = 0;
		return b; // b為最大公約數
	}
	// 下面的x、y交換是很直觀的根據推到式子來的
	int ret = exgcd2(b, a%b, x, y);
	int t = x;
	x = y;
	y = t - a/b*y;
	return ret;
}

線性求逆元

  • 注意:求逆元往往涉及大量的乘法,所以運算的時候一定要注意是否需要用到 long long。

總結