資訊競賽的數學

暖身

冷知識:數學的分類

數奧四大項:

  • A: 代數
  • C: 組合
  • G: 幾何
  • N: 數論

非競賽 e.g. 微積分

油宅四大項:

  • A: 動畫
  • C: 漫畫
  • G: 遊戲
  • N: 小說

其他 e.g. ???

結論: 數奧國手和油宅有很大的相似之處

VS.

有趣的題目

計算 \(a^b\)

次方

硬做?

複雜度: \(O(b)\)

好像有點慢...

快速冪:考慮分治

想計算\(a^b\),若已知 \(c=a^{\lfloor \frac{b}{2}\rfloor}\)

若 \(b\) 是偶數,則 \(a^b=c^2\)

若 \(b\) 是奇數,則 \(a^b=a \times c^2\)

 複雜度: \(O(logN)\)

扣(遞迴版)

int exp(int a, int b, int m){
    if(b==0) return 1;
    if(b%2){
        return a*exp(a,b-1,m)%m;
    } else{
        int tmp=exp(a,b/2,m);
        return tmp*tmp%m;
    }
}

扣(迭代版)

int exp(int a, int b, int m){
    int c=1, e=a;
    while(b>0){
        if(b%2){
            c=(c*e)%m;
        }
        e=(e*e)%m;
        b/=2;
    }
    return c;
}

矩陣

矩陣

某個看起來很像二維陣列的東西

\begin{bmatrix} a&b\\c&d\\e&f \end{bmatrix}

橫的稱為列

直的稱為行

矩陣加法

對應的位置相加

\begin{bmatrix} 1&2\\3&6\\4&7 \end{bmatrix} + \begin{bmatrix} 3&7\\5&1\\4&2\end{bmatrix} = \begin{bmatrix} 4&9\\8&7\\8&9 \end{bmatrix}

矩陣乘法

\begin{bmatrix} 1&2\\4&6 \end{bmatrix} + \begin{bmatrix} 5&1\\3&2\end{bmatrix} = \begin{bmatrix} 11&38\\5&16 \end{bmatrix}

將一 \(m\times n\)的矩陣 \(A\) 和 \(p\times q\)的矩陣 \(B\) 相乘

條件: \(n\) 必須等於 \(p\),相乘後的矩陣 \(C\) 為 \(m\times q\)

且\(C_{ij}=\sum_{k=1}^{n}A_{ik}B_{kj}\)

typedef vector<vector<int> > matrix;
matrix mul(matrix a, matrix b){
    matrix c=matrix(a.size(),vector<int>(b[0].size(),0));
    for(int i=0;i<a.size();i++){
        for(int j=0;j<b[0].size();j++){
            for(int k=0;k<a[0].size();k++){
                c[i][j]+=a[i][k]*b[k][j];
            }
        }
    }
    return c;
}

複雜度: \(O(n^3)\)

還能更快?

矩陣快速冪

矩陣乘法 -> 矩陣冪 -> 矩陣快速冪

作法就把前面實數乘法改成矩陣乘法

複雜度: \(O(n^3logk)\)

OJDL 7052

https://ojdl.ck.tp.edu.tw/problem/7052

求費氏數列前綴 \(k\) 次的第 \(n\) 項

\(k\leq 5, n\leq 10^{18}\)

TIOJ 2151

https://tioj.ck.tp.edu.tw/problems/2151

去年有趣的校內賽題

高斯消去

以後講?

或者你可以做這題

https://tioj.ck.tp.edu.tw/problems/2170

組合

排列數與組合數

\(C_m^n\) : \(n\) 個相異物品取 \(m\) 個的方法數

\(C_m^n=\frac{n!}{m!(n-m)!}\)

\(P_m^n\) : \(n\) 個相異物品取 \(m\) 個排成一排的方法數

\(P_m^n=\frac{n!}{(n-m)!}\)

計算

\(O(N)\)預處理階乘

或是利用性質

\(C_m^n=C_{m-1}^{n-1}+C_m^{n-1}\)

TIOJ 2163

https://tioj.ck.tp.edu.tw/problems/2163

題敘有點長 自己看

許多組合題使用DP的技巧

詳情見8e7orz的講義

數論

是什麼

關於"整數"的學問

(有時也會討論有理數)

同餘

同餘--定義

\(a\equiv b  (mod  m)\)

表示a除以m的餘數和b除以m的餘數相同

如: \(9\equiv 2  (mod\ 7)\)

同餘--性質

加法: \(a\equiv b  (mod  m)  \Leftrightarrow  a+c\equiv b+c  (mod  m) \)

乘法: \(a\equiv b  (mod  m)  \Rightarrow  ac\equiv bc  (mod  m) \)

注意: 不一定能除

整除

整除符號 \(a\mid b\)

表示存在一整數 \(k\) 使得 \(b=ak\)

ex. \(3\mid 12、87\mid 0、-2\mid 22\)

GCD與LCM

gcd: 最大公因數

lcm: 最小公倍數

\(gcd(a,b)\times lcm(a,b) = a\times b\)

why?

如何求?

輾轉相除

性質:\(gcd(a,b)=gcd(b,a\% b)\)

當其中一個為0時,gcd就是另一個

int gcd(int a, int b){
    if(b==0) return a;
    return gcd(b,a%b);
}

複雜度: \(O(logN)\)

Why?

模下的線性方程

我們想解這個

\(ax\equiv b  (mod  m)\)

不能除怎麼辦?

模逆元

一數字 \(a\) 在模 \(m\) 下的模逆元 \(a^{-1}\) 滿足

  • \(0< a^{-1}< m\)
  • \(a\cdot a^{-1}=1\)

不一定存在! 條件: \(gcd(a,m)=1\)

如何求?

費馬小定理

給定一質數 \(p\) 與一比 \(p\) 小的數 \(a\),恆有

a^{p-1}\equiv 1\ (mod\ p)

證明?

如何求?

\(a^{p-1}\equiv 1\ (mod\ p)\)

\(\Rightarrow a\cdot a^{p-2}\equiv 1  (mod  p)\)

所以 \(a^{p-2}\) 即為 \(a\) 的模逆元

非質數的情況

擴展歐幾里德(增強輾轉相除)

貝祖定理: 對於兩數 \(a,b\),存在無限多組整數 \(x,y\)

使得 \(ax+by=gcd(a,b)\)

作法

已知 \(gcd(a,m)=1\)

我們想找到一個 \(b\),使得 \(ab\equiv 1  (mod  m)\)

存在 \(k\) 使得 \(ab-mk=1\)

給定 \(a,m\),求出 \(b,k\) 即可!

遞迴看看

想要求\(ax+by=1\)的解

若已知 \(x',y'\) 滿足 \(bx'+(a\%b)y'=1\)

要怎麼得到解?

bx'+(a\%b)y'=1\\ bx'+(a-\lfloor \frac{a}{b} \rfloor b)y'=1\\ ay'+b(x'-\lfloor \frac{a}{b} \rfloor y')=1\\ \Rightarrow x=y',\ y=x'-\lfloor \frac{a}{b} \rfloor y'

實作

void extgcd(int a, int b, int &x, int &y, int &d){
    if(b==0){ 
        d = a;
        x = 1;
        y = 0;
        return;
    } else {
        extgcd(b, a % b, x, y, d);  
        int nx, ny;
        nx = y;
        ny = x - a/b * y;
        x = nx;
        y = ny;
        return;
    }
}

OJDL 7044

質數

求某個數是不是質數

bool isPrime(int n){
    for(int i=2;i*i<=n;i++){
        if(n%i==0){
            return false;
        }
    }
    return true;
}

複雜度: \(O(\sqrt N)\)

求\(1\)~\(N\)的所有質數

用上一頁的方法一個一個硬做

複雜度: \(O(N\sqrt N)\)

好像有點慢...

埃拉托斯特尼篩法

做法: 一開始所有數都是質數,

從 \(2\) 開始,將自己所有的倍數都標記為"不是質數"

1 2 3 4 5 6 7 8 9 10

How fast?

複雜度: \(N\cdot \sum_{k=1}^{N} \frac{1}{k}=O(NlogN)\)

優化:

  • 可以遇到質數再開始篩
  • 不用從 \(2i\) 開始跑,可以從 \(i^2\)

最終複雜度: \(N\cdot \sum_{p\leq N} \frac{1}{p}=O(N  log  log  N)\)

跟線性差不了多少(?

Code

const int MAXN=1E5;
bool isPrime[MAXN+1];
void getPrimes(){
    for(int i=0;i<=MAXN;i++) isPrime[i]=1;
    isPrime[0]=isPrime[1]=0;
    for(ll i=2;i<=MAXN;i++){
        if(isPrime[i]){
            for(ll j=i;i*j<=MAXN;j++){
                isPrime[i*j]=0;
            }
        }
    }
}

線性篩 by Euler

我們想要每個合數都被篩掉一次!

每個合數\(N\)都有最小質因數 \(p_{min}\)

我們想在 \(i=\frac{N}{p_{min}}\)時被篩掉

作法

若目前在 \(i\) 且沒被篩掉,則 \(i\) 為質數。

維護一個目前的所有質數的陣列,對於每個質數 \(p\) :

  • 若 \(p\times i>N\) 則跳出
  • 否則 \(p\times i\) 是合數,且 \(p\) 是 \(p\times i\) 的最小質因數
  • 若 \(i\) 為 \(p\) 的倍數,則跳出

Huh?

  • 若 \(i\) 為 \(p\) 的倍數,則跳出

\(p\) 會是 \(i\) 的最小質因數,所以後面的數會被 \(p\) 篩掉,不用急!

複雜度: \(O(N)\)

Code

const int MAXN=1E5;
bool isPrime[MAXN+1];
vector<int> primes;
void getPrimes(){
    for(int i=0;i<=MAXN;i++) isPrime[i]=1;
    for(int i=2;i<=MAXN;i++){
        if(isPrime[i]) primes.push_back(i);
        for(auto p:primes){
            if(i*p>MAXN) break;
            isPrime[i*p]=0;
            if(i%p==0) break;
        }
    }
}

質因數分解

維護\(1\)~\(\sqrt N\)的質數,再一個個驗證

原因: 對於一個數字\(N\),至多一個質因數大於\(\sqrt N\)

EasyLa

vector<int> primes; //用前面質數篩法預處理好
vector<pii> factorize(int n){
    vector<pii> vec;
    pii tmp;
    for(auto p:primes){
        if(p*p>n) break;
        if(n%p==0){
            tmp={p,0};
            while(n%p==0){
                tmp.S++;
                n/=p;
            }
            vec.push_back(tmp);
        }
    }
    if(n>1) vec.push_back({n,1});
    return vec;
}

TIOJ 1668

https://tioj.ck.tp.edu.tw/problems/1668

求 \([l,r]\) 內的質數數量

\(r-l\leq 2\cdot 10^5\)

中國剩餘定理

有物不知其數,三三數之剩二,五五數之剩三,七七數之剩二。問物幾何?

<孫子算經>

下卷第二十六題 物不知數

x\equiv 2\ (mod\ 3)\\ x\equiv 3\ (mod\ 5)\\ x\equiv 5\ (mod\ 7)

方法1. 構造解

x\equiv a_1\ (mod\ m_1)\\ x\equiv a_2\ (mod\ m_2)
x=a_1\cdot m_2\cdot (m_2^{-1}\ (mod\ m_1))+a_2\cdot m_1\cdot (m_1^{-1}\ (mod\ m_2))

模 \(m_1\) 為 \(1\)

模 \(m_2\) 為 \(0\)

模 \(m_1\) 為 \(0\)

模 \(m_2\) 為 \(1\)

如果只有兩條式子

方法1. 構造解

x=\sum_{i=1}^{n} a_iM_i\mu_i\ (mod\ lcm(m_i))

推廣到 \(n\) 條式子的情形

定義 \(M_i=\prod_{k=1,k\neq i}^{n} m_k\)

\(\mu_i=M_i^{-1}(mod  m_i)\)

則 \(M_i\mu_i\) 在模 \(m_i\) 時為\( 1\),

在模其他的 \(m_j\) 為 \(0\),故構造

方法2. 擴展歐幾里德

一樣先考慮兩條式子

x\equiv a_1\ (mod\ m_1)\\ x\equiv a_2\ (mod\ m_2)
x=m_1k_1+a_1=m_2k_2+a_2\\ m_1k_1-m_2k_2=a_2-a_1

方法2. 擴展歐幾里德

\(m_1k_1-m_2k_2=a_2-a_1\)

\(ax+by=c\) ?

若 \(a_2-a_1\nmid gcd(m_1,m_2)\) 則無解

否則可以求出 \(k_1\) 的值,然後代回去

得到某種 \(x\equiv m_1k_1+a_1  (mod  lcm(m_1,m_2))\)

剩下\(n-1\)條式子,可以繼續做下去

計算幾何

大部分是資芽講義抄來的

內積、外積

typedef pair<int,int> pii;
#define F first
#define S second

//內積
int operator*(const pii &a, const pii &b){
    return a.F*b.F+a.S*b.S;
}
//外積
int operator^(const pii &a, const pii &b){
    return a.F*b.S-a.S*b.F;
}

多邊形有向面積

線段相交

給定兩線段,求是否相交

可以發現若兩線段相交,只有兩種case:

(1) 一線段的一個端點在另一線段上

(2) 兩線段的兩端點都分別在另一線段兩側

Case 1

Case 2

不相交

四個點只要有一個就可

兩邊都要判

Code

極角排序

給定一堆點,將他們依照對原點的角度排序

方法一: sort by angle

bool cmp1(pii a, pii b){
    return atan2(a.S,a.F)<atan2(b.S,b.F);
}

方法二: sort by cross

bool cmp2(pii a, pii b){
    bool f1 = a<pii(0,0);
    bool f2 = b<pii(0,0);
    if(f1!=f2) return f1<f2;
    return a^b>0;
}

基本上建議用方法二,因為不會有浮點數誤差的問題

凸包

給定很多點,將所有點用最小的凸多邊形包起來,

稱為凸包。

作法

分別考慮上半部和下半部

將所有點先照座標排序,依序考慮每個點

開一個stack(或是vector)紀錄目前的凸包

類似單調對列的概念,每加進一個點,就看哪些點必須被移除

紅點加入後

移除藍點

紅點加入後

保留藍點

大家可以練習一下

Made with Slides.com