數論
數論在幹嘛
探討整數問題
舉例
- 進位制
 - 質數、合數
 - 因數、倍數
 - 輾轉相除法
 
進位制
會平常會用到的進位制
- 十進位
 - 時間(分, 秒)
 - 電腦的二進位
 
進位制表示法
在右下角加上下標
\(數值_n\)
\(1101_2\)
換一種方式來看進位制
以十進位為例
一個十進位數\(=\)第\(i\)位數\( \times 10^{i - 1}\) 的和
換一種方式來看進位制
再看看二進位
一個二進位數\(=\)第\(i\)位數\( \times 2^{i - 1}\) 的和
換一種方式來看進位制
推廣到n進位
一個n進位數\(=\)第\(i\)位數\( \times n^{i - 1}\) 的和
會了這個就可以來做進位制轉換
先把數字轉成我們最熟悉的十進位,再轉成其他的
質數
因數只有1和自己
質數判斷
//isp(x)判斷x是不是質數
bool isp(int x){
    for(int i=2;i<x;i++){
    	if(x%i==0) return 0;
    }
    return 1;
}就判斷x有沒有除了1跟x以外的因數
好像有點慢?
質數判斷
//isp(x)判斷x是不是質數
bool isp(int x){
    for(int i=2;i*i<=x;i++){
    	if(x%i==0) return 0;
    }
    return 1;
}質數篩
//isp(x)判斷x是不是質數
bool prime[1000000];
bool isp(int x){
    for(int i=2;i*i<=x;i++){
    	if(x%i==0) return 0;
    }
    return 1;
}
int main(){
    for(int i=1;i<1000000;i++){
    	prime[i]=isp(i);
    }
}線性質數篩
//vector是一種長度可變的陣列
bool notprime[1000000];
vector<int> prime;
int main(){
    for(int i=2;i<1000000;i++){
        if(!notprime[i]) prime.push_back(i);
        for(int j:prime){
            if(i*j>=1000000) break;
            notprime[i*j]=1;
            if(i%j==0) break;
        }
    }
}線性質數篩改
//minp[i]紀錄i的最小質因數
int minp[10000000];
vector<int> prime;
int main(){
    for(int i=2;i<10000000;i++){
        if(!minp[i]) prime.push_back(i),minp[i]=i;
        for(int j:prime){
            if(i*j>=10000000) break;
            minp[i*j]=j;
            if(i%j==0) break;
        }
    }
}可以做質因數分解
同餘
同餘
同餘
在等號兩邊一起加減乘不會影響結果
但除法會是錯的
對負數的同餘
由餘數的定義可以知道\(a\)除以\(m\)
可表示成\(a = mq + r\),r是餘數
但如果\(a<0\)
那r可以是正的也可以是負的
例如:
\(-5除以2的餘數可以是-1也可以是1\)
對負數的同餘
在不同的程式語言有不同的結果
C++: (-5) % 2 = -1
Python:(-5) % 2 = 1
快速冪
快速冪
//算x^p
int pow(int x,int p){
    int res=1;
    while(p--) res*=x;
    return res;
}一點也不快?
快速冪
快速冪
//算x^p
int pow(int x,int p){
    if(p==1) return x;
    int res=pow(x,p/2);
    res*=res;
    if(p%2==1) res*=x;
    return res;
}快速冪
二進位分解
以此類推,把我們要的位元乘起來
快速冪
二進位分解
//算x^p
int pow(int x,int p){
    int res=1;
    for(;p>0;p/=2,x*=x)
        if(p%2==1)
            res*=x;
    return res;
}小心不要overflow
輾轉相除法
快速求得兩數的最大公因數
\(gcd(a, b)\)
又稱歐基里得算法
需要的性質
當b不是a的因數時
\(gcd(a, b)=gcd(b, a\%b)\)
\(gcd(64, 42) = gcd(42, 22) = gcd(22, 20) = gcd(20, 2) = 2\)
證明
\(gcd(a, b) = gcd(b, a\%b)\)
令\(a = rb+q, q = a\%b\)
令\(d = gcd(a,b)\)
\(\because d|a\)
\(\therefore rb + q\equiv 0\pmod d\)
證明
\(gcd(a, b) = gcd(b, a\%b)\)
令\(a = rb+q, q = a\%b\)
令\(d = gcd(a,b)\)
\(\because d|a\)
\(\therefore rb + q\equiv 0\pmod d\)
\(\because d|b\)
\(\therefore b\equiv 0\pmod d\)
\(\because rb \equiv 0\pmod d\)
\(\therefore rb+q\equiv 0 + q\equiv 0\pmod d\)
\(q\equiv 0\pmod d\)
證明
\(gcd(a, b) = gcd(b, a\%b)\)
\(q\equiv 0\pmod d\)
\(a\%b\equiv 0\pmod d\)
\(d|a\%b, b\)
現在我們已經知道\(gcd(a, b)\)是\(b\)和\(a\%b\)的因數
那會不會有\(gcd(b, a\%b)>gcd(a, b)\)?
證明
\(gcd(a, b) = gcd(b, a\%b)\)
假設\(b, a\%b有公因數d'\)
\(且d'>gcd(a, b)\)
\(a = rb+q\)
證明
\(gcd(a, b) = gcd(b, a\%b)\)
假設\(b, a\%b有公因數d'\)
\(且d'>gcd(a, b)\)
\(a = rb+q\)
\(q=a\%b\)
\(rb\equiv 0\pmod {d'}\)
\(q\equiv 0\pmod {d'}\)
\(rb+q\equiv 0+0\equiv 0\pmod {d'}\)
\(a\equiv 0\pmod {d'}\)
證明
\(gcd(a, b) = gcd(b, a\%b)\)
\(\because a\equiv 0\pmod{d'}\)
\(\therefore d'|a, b\)
\(gcd(a, b) >= d'\)
與假設矛盾
遞迴想法
如果\(b|a\),則\(gcd(a, b) = b\)
否則\(gcd(a, b) = gcd(b, a\%b)\)
int gcd(int a,int b){
    if(b==0) return a;
    return gcd(b,a%b);
}實作
擴展歐幾里得
透過歐基里得算法的性質
已知整數\(a, b\)
可計算\(ax+by=gcd(a, b)\)
\(x和y的解\)
擴展歐基里得
令\(ax_1+by_1 = gcd(a, b)\)
令\(bx_2 + (a\%b)y_2=gcd(b, a\%b)\)
擴展歐基里得
令\(ax_1+by_1 = gcd(a, b)\)
令\(bx_2 + (a\%b)y_2=gcd(b, a\%b)\)
由歐基里得算法可知
\(gcd(a, b) = gcd(b, a\%b)\)
擴展歐基里得
令\(ax_1+by_1 = gcd(a, b)\)
令\(bx_2 + (a\%b)y_2=gcd(b, a\%b)\)
由歐基里得算法可知
\(gcd(a, b) = gcd(b, a\%b)\)
\(ax_1+by_1=bx_2+(a\%b)y_2\)
擴展歐基里得
令\(ax_1+by_1 = gcd(a, b)\)
令\(bx_2 + (a\%b)y_2=gcd(b, a\%b)\)
由歐基里得算法可知
\(gcd(a, b) = gcd(b, a\%b)\)
\(ax_1+by_1=bx_2+(a\%b)y_2\)
\(a\%b=a-\lfloor a/b\rfloor b\)
擴展歐基里得
令\(ax_1+by_1 = gcd(a, b)\)
令\(bx_2 + (a\%b)y_2=gcd(b, a\%b)\)
由歐基里得算法可知
\(gcd(a, b) = gcd(b, a\%b)\)
\(ax_1+by_1=bx_2+(a\%b)y_2\)
\(a\%b=a-\lfloor a/b\rfloor b\)
\(ax_1 + by_1 = bx_2+(a-\lfloor a/b\rfloor b)y_2\)
\(ax_1 + by_1 = bx_2+ay_2-\lfloor a/b\rfloor by_2\)
擴展歐基里得
\(ax_1 + by_1 = bx_2+ay_2-\lfloor a/b\rfloor by_2\)
擴展歐基里得
\(ax_1 + by_1 = bx_2+ay_2-\lfloor a/b\rfloor by_2\)
\(ax_1 + by_1 = ay_2 + b(x_2 - \lfloor a/b\rfloor y_2)\)
\(x_1 = y_2, y_1 = x_2 - \lfloor a/b\rfloor y_2\)
遞迴想法
\(x_2, y_2是bx + (a\%b)y = gcd(b, a\%b)的解\)
所以只要求出\(bx+(a\%b)y=gcd(b, a\%b)\)
就可以透過\(x_1 = y_2, y_1 = x_2 - \lfloor a/b\rfloor y_2\)
推出\(ax+by=gcd(a, b)\)的解
遞迴終止條件
\(ax+by=gcd(a, b)\)
如果\(b|a\)
則\(ax+by=b\)
\(x = 0, y = 1\)
實作
pair<int, int> exgcd(int a, int b){
	if(a % b == 0){
    	return {0, 1};
    }
    pair<int, int> tmp = exgcd(b, a % b);
    return {tmp.second, tmp.first - a/b * tmp.second};
}void exgcd(int a, int b, int &x, int &y){
	if(a % b == 0){
    	x = 0; y = 1;
        return;
    }
    exgcd(b, a%b, y, x);
    y = y - a / b * x;
}模逆元
在同餘下的除法
模逆元
除法不能用,但可以乘以倒數
模逆元只有在\(a, m互質時存在\)
證明
如果\(a, m\)不互質
存在一個大於1的整數\(d\)使\(a=da', m=dm'\)
設x為一任意整數
試證明\(ax\%m \ne 1\)
\(ax = da'x\)
\((da'x)\%(dm')=d(a'x\%m')\)
\(\because d>1\)
\(\therefore d(a'x\%m') \ne 1\)
\(ax\% \ne 1\)
模逆元
擴展歐幾里得
費馬小定理/歐拉函數
費馬小定理/歐拉函數
費馬小定理
\(a^{p - 1} \equiv 1\pmod p\)
\(a\times a^{p - 2}\equiv 1\pmod p\)
\(\because a\times a^{-1}\equiv 1\pmod p\)
且\(a\times a^{p-2}\equiv 1\pmod p\)
\(\therefore a^{-1} \equiv a^{p-2}\pmod p\)
費馬小定理的推廣
歐拉函數
要先證明一些東西
歐拉函數
歐拉函數
| 1 | 2 | 3 | 
| 4 | 5 | 6 | 
| 7 | 8 | 9 | 
| 10 | 11 | 12 | 
| 13 | 14 | 15 | 
| 16 | 17 | 18 | 
| 19 | 20 | 21 | 
| 22 | 23 | 24 | 
| 25 | 26 | 27 | 
歐拉函數
將n質因數分解
將次方提出來
歐拉函數
整理一下
實作
其實就只是質因數分解
尤拉定理
中國剩餘定理
中國剩餘定理
設\(n=3\times 5\times 7t + 3\times 5r + 3s + q\)
則\(n \equiv q\pmod 3\)
\(n\equiv 3\times s+q\pmod 5\)
\(n\equiv 3\times 5r + 3s+q\pmod 7\)
中國剩餘定理
用這個方式就可以推出n
中國剩餘定理
解一個有\(k\)項的中國剩餘定理
其中任意兩\(m_i, m_j\)互質
令\(M = m_1\times m_2\times m_3 ... \times m_k\)
令\(M_i = M/m_i\)
\(n = a_1M_1M_1^{-1} + a_2M_2M_2^{-1}+...a_kM_kM_k^{-1}\)
數論
By scottchou
數論
- 260