數學知識(數論)(持續更新中...)

素數

定義

請自行百度。。。html

質數的斷定

1. 試除法算法

若一個正整數$N$爲合數,則存在一個能整除$N$的正整數$T$,其中$ 2≤T≤\sqrt{N} $app

證實:略ide

簡易代碼:函數

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

複雜度:顯而易見試除法的時間複雜度爲 $O(\sqrt{N})$ .優化

至於 \(Miller-Robbin\)算法 ,戳這裏spa

質數篩法

即給定一個整數$N$,求出1~$N$之間全部質數3d

1. $Eratosthenes$篩法code

算法思想:htm

任意整數$x$的倍數$2x$、$3x$ $\cdots$ 均不是質數

實現步驟:

從$2$開始,一直掃到$N$,把他們的倍數 $2x$、$3x$、 $\cdots$ 、$\left \lfloor \frac{N}{x} \right \rfloor * x$ 標記爲不是質數。

若掃到某個數沒有被標記,則該數是質數。

簡易代碼:

void make_prime_list(int n)
{
    memset(vis,false,sizeof vis);
    for(int i=2;i<=n;++i)
    {
        if(vis[i]) continue;
        printf("%d ",i);
        for(int j=i;i*j<=n;++j) vis[i*j]=1;
    }
}

複雜度:藍書上寫的是 \(O(\sum_{質數p≤N} \frac{N}{p}) = O(N\log \log N)\)其實我也不太會證實

2. 線性篩法(歐拉篩)

優化原理:

咱們發現,上述篩法中不可避免的要對一個數重複標記。如:$12$ 既會被 $6*2$ 篩掉,也會被 $4*3$ 篩掉。如圖:

vis[ i ] vis[ i * j ]
2 4,6,8,10,12 \(\cdots\)
3 6,9,12,15,18 \(\cdots\)
\(\cdots\) \(\cdots\)

那麼有沒有什麼辦法能夠對每一個數只篩一次呢?答案是確定的。

咱們能夠只用每一個數的最小質因子去篩它。

線性篩法實現步驟

  • 首先從 \(2\)~\(N\) 循環一遍

  • \(i\) 沒有被標記,則將它加入質數表中

  • 掃描已有的小於 \(\left \lfloor \frac{N}{i} \right \rfloor\) 的質數 \(p_j\) ,標記 \(i*p_j\) ;當 \(p_j\) 能夠整除 \(i\) 時,則說明此時 \(p_j\) 已不是 \(i*p_j\)的最小質因子,即跳出循環。

優化後的標記過程(如取 $N=20$):

vis[ i ] vis[ i * pri[ j ] ]
2 4
3 6,9
4 8
5 10,15
6 12
7 14
8 16
9 18
10 20
11,12 \(\cdots\) 20

簡易代碼:

void make_prime_list(int n)
{
    for(int i=2;i<=n;++i)
    {
        if(!vis[i]) pri[++tot]=i;
        for(int j=1;j<=tot && pri[j]*i<=n;++j)
        {
            vis[pri[j]*i]=1;
            if(i%pri[j]==0) break;
        }
    }
}

時間複雜度:由於每一個合數 $i*p_j$ 只會被它的最小質因子 $p_j$ 篩一次,因此時間複雜度爲 $O(N)$ 。

算術基本定理

  • 定義:算術基本定理,又稱爲正整數的惟一分解定理,即:每一個大於1的天然數,要麼自己就是質數,要麼能夠寫爲2個或以上的質數的積,並且這些質因子按大小排列以後,寫法只有一種方式

  • 用數學語言表示,即爲:\(\forall A\in\mathbb{N},\,A>1\ \exists \prod_{i=1}^n p_i^{a_i}=A\)。其中 \(p_1<p_2<p_3<\cdots<p_n\)\(p_i\) 爲一個質數,\(a_i\in\mathbb{Z}^+\)

  • 推論:見\(2.2\)

質因數分解

1. 試除法

  • 由算術基本定理可得,將\(\left[2,\sqrt{N}\right]\)的數掃一遍,其中必然能夠將 \(N\) 的質因子從小到大地除去。

  • 複雜度:顯而易見的是 \(O(\sqrt{N})\)

  • 簡易代碼:

const int N=100005;
int pri[N],count[N],n;
inline void prime_divide(int n)
{
    int cnt=0;
    for(int i=2;i*i<=n;++i)
    {
        if(n%i==0)
        {
            pri[++cnt]=i,count[cnt]=0;
            while(n%i==0) n/=i,++count[cnt];
        }
    }
    if(n>1) pri[++cnt]=n,count[cnt]=1;
    for(int i=1;i<=cnt;++i) printf("%d^%d\n",pri[i],count[i]);
}

至於 \(Pollard\ Rho\)算法 ,戳這裏

約數

定義

設 $a,b$ 知足 $a\in\mathbb{N}^+ \,\ b\in\mathbb{N}$ 。若 $\exists \ \ q\in\mathbb{N}$ ,使得 $b = a \times q$ , 那麼就說 $b$ 是 $a$ 的倍數, $a$ 是 $b$ 的約數。這種關係記做 $a \mid b$ ,讀做" $a$ 整除 $b$"。

算數基本定理的推論

  • 在算數基本定理中,若正整數 \(N\) 被惟一分解爲 \(N = p_{1}^{c_1} p_{2}^{c_2} \cdots p_{m}^{c_m}\) ,其中 $c_i \in\mathbb{N}^+ $, \(p_i\)均爲質數,且知足 \(p_1 < p_2 < \cdots <p_m\) ,則 \(N\) 的正約數集合可寫爲:

    \[ \{{p_{1}^{b_1} p_{2}^{b_2} \cdots p_{m}^{b_m}} \} ,其中 0≤b_i≤c_i\]

  • \(N\) 的正約數個數爲:

    \[ (c_1+1) \times (c_2+1) \times \cdots \times (c_m+1) = \prod_{i=1}^{m} {(c_i+1)}\]

  • \(N\) 的全部正約數的和爲:

    \[ (1 + p_1 + p_1^{2} + \cdots +p_1^{c_1} ) \times \cdots \times (1 + p_m + p_m^{2} + \cdots +p_m^{c_m} ) = \sum_{i=1}^{m} (\prod_{j=0}^{c_i} {p_i^j}) \]

  • 由等比數列相關知識,上述式子可變爲:

    \[ \prod_{i=1}^{m} (\frac{1 - p_i^{c_i+1}}{1 - p_i}) \]

求正約數集合

1. 試除法(求$N$的正約數集合)

  • \(d≥ \sqrt{N}\)\(N\) 的約數,則 \(\frac{N}{d} ≤ \sqrt{N}\) 也是 \(N\) 的約數。(當 \(\sqrt{N} \in\mathbb{N}^+\),需特判一下)

  • 因此,只需線性掃描一遍 \(d = 1\) ~ \(\sqrt{N}\) ,複雜度爲 \(O(\sqrt{N})\)

  • 推論:一個整數 \(N\) 的約數個數上界爲 \(2\sqrt{N}\)

  • Code:
const int N=100005;
int factor[N],cnt,n;
inline void factor_Search(int n)
{
    for(int i=1;i*i<=n;++i)
    {
        if(n%i==0)
        {
            factor[++cnt]=i;
            if(i*i!=n) factor[++cnt]=n/i;
        }
    }
    for(int i=1;i<=cnt;++i) printf("%d ",factor[i]);
}

2. 倍數法(求 $1$ ~ $N$ 的每一個數的正約數集合)

  • 對於每一個整數 \(d \in \left[1,N \right]\)\(1\) ~ \(N\) 中以 \(d\) 爲約數的數就是 \(d\) 的倍數: \(2d\)\(3d\)\(\cdots\)\(\left \lfloor \frac{N}{d} \right \rfloor * d\)

  • 時間複雜度:\(O(N + \frac{N}{2} + \frac{N}{3} + \cdots + \frac{N}{N})\) = \(\cdots\)證實有點多,不想寫) = \(O(N \times ( \ln(N+1) + r ))\)\(r\) 即爲著名的歐拉常數, \(r \approx 0.5772156649\) ) = \(O(N\log N)\)

  • Code:
const int N=1e6+5;
vector<int>factor[N];
for(int i=1;i<=n;++i)
    for(int j=1;j*i<=n;++j)
        factor[i*j].push_back(i);
for(int i=1;i<=n;++i)
{
    for(int j=0;j<factor[i].size();++j) printf("%d ",factor[i][j]);
    putchar('\n');
}

最大公約數

定義

若天然數 $d$ 同時是天然數 $a$ 、$b$ 的約數,則稱 $d$ 是 $a$、$b$ 的公約數。其中,$a$ 、$b$ 的公約數中最大的一個,稱做 $a$ 和 $b$ 的最大公約數,記做 $\gcd(a,b)$。

同理,若天然數 $m$ 同時是天然數 $a$ 、$b$ 的倍數,則稱 $m$ 是 $a$、$b$ 的公倍數。其中,$a$ 、$b$ 的公倍數中最小的一個,稱做 $a$ 和 $b$ 的最小公倍數,記做 $lcm(a,b)$。

幾個定理:

  1. \[ \forall a,b \in\mathbb{N} \quad \gcd(a,b) \times lcm(a,b) = a \times b \]

  2. \[\forall a,b,c \in\mathbb{N} \quad \gcd(a,lcm(b,c)) = lcm(\gcd(a,b),\gcd(a,c)) \]

  3. \[\forall a,b,c \in\mathbb{N} \quad lcm(a,\gcd(b,c)) = \gcd(lcm(a,b),lcm(a,c)) \]

    這裏只簡要證實 \(1\)

  • \(d = \gcd(a,b)\ ,a_0 = \frac{a}{d}\ ,b_0 = \frac{b}{d}\) 。由 \(gcd\) 的定義,有 \(\gcd(a_0,b_0) = 1\) ;由 \(lcm\) 的定義,有 \(lcm(a,b) = a_0 \times b_0\)

  • $\Rightarrow  $ \(lcm(a,b) = lcm(a_0 \times d,b_0 \times d) = lcm(a_0,b_0) \times d = a_0 \times b_0 \times d = \frac{a \times b}{d} = \frac{a \times b}{\gcd(a,b)}\)

gcd的求法

1. 九章算術 $\cdot$ 更相減損術

  • \(\forall a,b \in\mathbb{N} \ ,a≥b\) ,有 \(gcd(a,b) = gcd(b,a-b) = gcd(a,a-b)\)

  • \(\forall a,b \in\mathbb{N}\) , 有 \(\gcd(2a,2b) = \gcd(a,b)\)

由 $gcd$ 的定義,第二條顯然成立。這裏只證實第一條。

  • \(d = \gcd(a,b)\ ,a = d \times k_1\ ,b = d \times k_2\),則 \(a-b = (k_1 - k_2) \times d\),由\(gcd\)定義得:\(\gcd(k_1,k_2) = 1\)

  • 先假設 \(\gcd(k_1 - k_2,k_2)>1\),設 \(k_1 = p \times m\ ,k_2 = q \times m\)\(p,q,m \in\mathbb{Z}\)\(p,q,m >1\)),則有 \(k1 = (p - q) \times m\)

  • $\Rightarrow  $ \(\gcd(k_1,k_2) = m\)\(\gcd(k_1,k_2) = 1\)矛盾。故假設不成立,故 \(\gcd(k_1 - k_2,k_2) = 1\)

  • $\therefore $ 由 \(gcd\) 定義得 \(\gcd(b,b - a) = d =\gcd(a,b)\)

2. 歐幾里得算法(展轉相除法)

  • \[\forall a,b \in\mathbb{N}\ ,b \ne 0 \qquad \gcd(a,b) = \gcd(b,a\%b)\]

證實

  • \(a<b\),則 \(\gcd(b,a\%b) = \gcd(b,a) = \gcd(a,b)\)

  • \(a≥b\) ,設 \(a = q \times b + r\) ,其中 \(0≤ r <b\) 。此時顯然有 \(r = a \% b\)

  • 對於 \(a,b\)任意公約數 \(d\) ,$\because d \mid a  , d \mid q \times b \quad \therefore d \mid (a - q \times b) \Rightarrow   d \mid r  $ \(\Rightarrow d\) 也是 \(b,r\) 的公約數

  • 反之亦成立。故 \(a,b\)公約數集合\(b,a \% b\)公約數集合相同。\(\Rightarrow \gcd(a,b) = \gcd(b,a \% b)\)

簡易代碼:

#define ll long long
template<typename TP>ll Gcd(TP a,TP b) {return !b?a:Gcd(b,a%b);}

總結:歐幾里得算法複雜度爲 $O(log(a+b))$ ,故很經常使用。不過若是涉及到高精度計算,仍是用更相減損術吧!

互質與歐拉函數

定義

$\forall a,b \in\mathbb{N}$ ,若 $\gcd(a,b) = 1$ ,則稱 $a,b$ 互質,記爲 $a\ \bot\ b$ ,同時:

  • 若是數域是 \(\mathbb {N^{+}}\) ,那麼 \(1\) 與全部正整數互質。

  • 若是數域是 \(\mathbb {Z}\) ,那麼 \(1\)\(-1\) 與全部整數互素,並且它們是惟一與 \(0\) 互素的整數。

對於三個或三個以上的整數互質,有兩種狀況:

  • 這些整數的最大公約數是 \(1\),咱們直接稱這些整數互素,也稱爲整集互素。以 \(\{ {6,8,9} \}\) 爲例:

    \(\gcd(6,8,9) = \gcd(\gcd(6,8),9) = \gcd(2,9) = 1\)

  • 這些整數是兩兩互質的。以 \(\{ {7,8,9} \}\) 爲例:

    \(\gcd(7,8) = \gcd(8,9) = \gcd(7,9) = 1\)

    \(\Rightarrow \gcd(7,8,9) = \gcd(7,\gcd(8,9)) = \gcd(8,\gcd(7,9)) = \gcd(9,\gcd(7,8)) = 1\)

注:兩兩互素是較爲嚴格的互素,若是一個整數集合是兩兩互素的,它也一定是整集互素,可是整集互素沒必要然是兩兩互素。

歐拉函數

注:如下內容主要摘自藍書

1. 定義:

  • $ \left[1,N\right] $ 中與 \(N\) 互質的數的個數被稱爲歐拉函數,記做 \(\varphi(N)\)

  • 若在算數基本定理中, \(N = p_1^{c_1}p_2^{c_2} \cdots p_m^{c_m}\) ,則:

    \[ \varphi(N) = N \times \frac{p_1-1}{p_1} \times \frac{p_1-1}{p_1} \times \cdots \times \frac{p_1-1}{p_1} = N \times \prod\limits_{p_i \mid N} (1 - \frac{1}{p_i})\]

  • 證實:設 \(p\ ,q\)\(N\) 的質因子,$ \left[1,N\right] $ 中 \(p\) 的倍數有 \(p\ ,2p\ ,3p\ ,\cdots \ ,\left \lfloor \frac{N}{p} \right \rfloor \times p\),共 \(\left \lfloor \frac{N}{p} \right \rfloor\) 個。同理, \(q\) 也是如此。若是把這 $\left \lfloor \frac{N}{p} \right \rfloor + \left \lfloor \frac{N}{q} \right \rfloor $ 個數去掉,那麼 \(p \times q\) 的倍數就被排除了兩次,須要加回來一次。所以,$ \left[1,N\right] $中不與 \(N\) 含共同質因子 \(p\)\(q\) 的個數爲:

    \[N - \frac{N}{p} - \frac{N}{q} + \frac{N}{pq} = N \times (1 - \frac{N}{p} - \frac{N}{q} + \frac{N}{pq}) = N (1 - \frac{1}{p}) (1 - \frac{1}{q})\]

    相似的,能夠對 \(N\) 的全部質因子使用上述方法,便可獲得 \(\varphi(N)\) 的值。

2. 相關性質:

  • \(\forall N > 1\quad , \sum\limits_{i = 1\ ,\gcd(i,N) = 1}^{N}(i) = N \times \frac{\varphi(N)}{2}\)

  • \(\gcd(a,b) = 1\),則 \(\varphi(ab) = \varphi(a)\varphi(b)\)(至於積性函數,之後再做詳細介紹)

  • \(p\) 是質數,若 \(p \mid n\)\(p^2 \mid n\) ,則 \(\varphi(N) = \varphi(\frac{N}{p}) \times p\)

  • \(p\) 是質數,若 \(p \mid n\)\(p^2 \nmid n\) ,則 \(\varphi(N) = \varphi(\frac{N}{p}) \times (p-1)\)

  • \(\sum_{d \mid N}\varphi(d) = N\)

    證實略 \(\cdots\)

3. $\varphi$ 的求法:

⑴ 單獨求 \(\varphi(N)\)

根據 \(\varphi\) 的公式,咱們只需在分解質因數的同時便可順便求出 \(\varphi\) 。複雜度顯而易見爲 \(O(\sqrt{N})\)

Code:

inline int phi(int n)
{
    int ans=n;
    for(int i=2;i*i<=n;++i)
        if(n%i==0)
        {
            ans=ans/i*(i-1);
            while(n%i==0) n/=i;
        }
    if(n>1) ans=ans/n*(n-1);
    return ans;
}

⑵ 求 \(\left[1,N\right]\) 中每一個數的 \(\varphi\)

  • 利用 \(Eratosthenes\) 篩法,根據公式,能夠在 \(O(NlogN)\) 的時間內求出。

Code:

const int N=100005;
int phi[N];
inline void Euler(int n)
{
    for(int i=1;i<=n;++i) phi[i]=i;
    for(int i=2;i<=n;++i)
        if(phi[i]==i)
            for(int j=i;j<=n;j+=i)
                phi[j]=phi[j]/i*(i-1);
}
  • 利用性質 \(3\ ,4\) 和線性篩,可在 \(O(N)\) 時間內求出。

Code:

bitset<10000005>vis;
int pri[N],phi[N],cnt;
inline Euler(int n)
{
    phi[1]=1;
    F1(i,2,n)
    {
        if(!vis[i]) pri[++cnt]=i,phi[i]=i-1;
        for(rg j=1;j<=cnt && pri[j]*i<=n;++j)
        {
            vis[pri[j]*i]=1;
            if(i%pri[j]==0)
            {
                phi[pri[j]*i]=pri[j]*phi[i];
                break;
            }
            else phi[pri[j]*i]=(pri[j]-1)*phi[i];
        }
    }
}
相關文章
相關標籤/搜索