有參考算法競賽進階指南。。html
1、質數
- 定義:質數(prime number)又稱素數,有無限個。一個大於1的天然數,除了1和它自己外,不能被其餘天然數整除,則稱之爲質數。
(1) 斷定:
對於數$N$,若之爲合數,則存在一個數$T$能整除它其中,$2<=T<=\sqrt{N}$算法
複雜度:$O(\sqrt{n})$函數
(2) 篩法:
對於數$N$,咱們要求出$1$ ~ $N$的全部素數。ui
直接介紹線性篩法,對於數$m$,咱們考慮僅用它的最小質因子$q$篩去它,這是線篩的最基本思想。url
#include <cstdio> const int N=1000010; int v[N],prime[N],cnt=0,n; //v[i]表明i的最小質因子,prime[i]表明第i的素數是多少 void Prime() { for(int i=2;i<=n;i++) { if(!v[i]) { v[i]=i; prime[++cnt]=i; } for(int j=1;j<=cnt;j++) { int k=prime[j]*i; if(v[i]<prime[j]||k>n) continue; v[k]=prime[j]; } } } int main() { scanf("%d",&n); Prime(); for(int i=1;i<=cnt;i++) printf("%d ",prime[i]); return 0; }
複雜度:$O(n)$spa
(3) 質因數分解
- 算術基本定理:任何一個大於1的整數都能被分解成有限個質數的乘積
即$N=p_1^{c^1}p_2^{c^2}...p_m^{c^m}$或$N=\prod_{i=1}^m{p_i}^{c_i}$.net
當不考慮順序時,分解具備惟一性code
這點在後面用的不少。htm
- 質因數分解: 和斷定是不是質數有點像,咱們用$1$ ~ $\sqrt{N}$中的每個數去試除$N$
複雜度:$O(\sqrt{N})$blog
2、約數
(1) 整除,約數
整除的概念:通常的,設a,b爲整數,且b≠0.若是存在整數q,使得a=bq,稱b整除a,記做$b|a$,也稱b是a的約數。若是p不存在,稱b不整除a,記做$b \nmid a$.
整除的性質:
a|b,b|a $\Rightarrow$ a=b或a=-b
a|b,b|c $\Rightarrow$ a|c
a|b,a|c $\Rightarrow$ 對任意整數x,y,有a|bx+cy
若$a|bc$,且$(a,b)$=$1$,則$a|c$
設p爲素數,若$p|ab$,則$p|a$或$p|b$ 設p爲素數,若$p|a_1a_2...a_k$,則存在$a_i$ $(1≤i≤k)$,使得$p|a_i$.
設整數 $a$ , $b$ 不一樣時爲0,則存在一對整數 $m$ , $n$ ,使得$(a,b)=am+bn$(在一次同餘方程和不定方程中常常用到)【裴蜀定理】
(2) 最大公約數與最小公倍數
-
定義:$gcd(a,b)$(或$(a,b)$)爲最大公因數,$lcm[a,b]$(或$[a,b]$)爲最小公倍數
-
歐幾里得算法:$(a,b)=(b,a$ $mod$ $b)$
歐幾里得就不證實了吧。
int gcd(int a,int b) { return b==0?a:gcd(b,a%b); }
- $(a,b)[a,b]=|a||b|$
(3) 算術基本定理的推論:
$N=p_1^{c^1}p_2^{c^2}...p_m^{c^m}$
-
$N$的正約數個數: $\prod_{i=1}^m (c^i+1)$
-
$N$的正約數之和: $(1+p_1+p_1^2+...+p_1^{c_1})...(1+p_m+p_m^2+...+p_m^{c_m})=\prod_{i=1}^m(\sum_{j=0}^{c_i} (p_i)^j)$
(4) 互質
對整數$a,b$,若$gcd(a,b)=1$,則稱$a$與$b$互質。
(5) 歐拉函數
- 定義:$1$ ~ $N$中與$N$互質的數的個數,稱爲歐拉函數,記爲$φ(N)$
- 計算式 對$N$進行算術基本定理分解,即$N=p_1^{c^1}p_2^{c^2}...p_m^{c^m}$或$N=\prod_{i=1}^m{p_i}^{c_i}$ 則$φ(N)=(1-1/p_1)(1-1/p_2)...(1-p_m)$即$φ(N)=\prod_{i=1}^m(1-1/p_i)$ 感性證實(即並非那麼確切的,只是能加深記憶的證實·): 對於$N$的某個質因子$p$,$pk$必定於$N$不互質($k\in N^,kp<N$),即篩去後爲$N-N/p$ 若此時引入第二個因子$q$,同理篩去$N/q$,可是多篩去了$q$與$p$的公共倍數,加回來,即爲 $N-N/p-N/q+N/(q*p)=N(1-1/p)(1-1/q)$,以此類推
計算式$O(\sqrt N)$求解$φ(N)$
ll get(ll k) { ll eu=k; for(ll i=2;i*i<=k;i++) { if(k%i==0) eu=eu*(i-1)/i; while(k%i==0) k/=i; } if(k>1) eu=eu*(k-1)/k; return eu; }
-
性質 *①若$gcd(a,b)=1$,則$φ(ab)=φ(a)φ(b)$ 感性證實:帶入歐拉函數定義式便可。 【拓展】 徹底積性函數:是指全部對於任何$a,b$都有性質$f(ab)=f(a)f(b)$的數論函數。 積性函數:是指全部對於$gcd(a,b)=1$的$a,b$都有性質$f(ab)=f(a)f(b)$的數論函數。 ②若質數$q$知足$q|n$且$q^2|n$,則$φ(q)=φ(n/q)q$ 代入計算式能夠獲得 ③若質數$q$知足$q|n$且$q^2 \nmid n$,則$φ(q)=φ(n/q)(q-1)$ 由積性函數性質獲得 ④$\sum_{d|n}φ(d)=n$ 先證實是積性函數,再討論單因子狀況便可 ⑤$φ(n)*n/2=\sum_{d},gcd(d,n)=1$ 若$gcd(x,n)=1$,則$gcd(n-x,n)=1$。即它們是成對存在的。 對於以上證實,其實本身多證幾遍就記住了。
-
求解$φ(N)$ 將$N$分解質因數後,代入定義式計算。 複雜度:$O(\sqrt{N})$
-
求解$φ(1)$~$φ(N)$ 藉助性質①②③和線性篩的思想。 咱們在線性篩篩去合數的同時推出這個合數的$φ(i)$ code:
int v[N],prime[N],phi[N],cnt=0,n; void eular() { for(int i=2;i<=n;i++) { if(!v[i]) { v[i]=i; prime[++cnt]=i; phi[i]=i-1; } for(int j=1;j<=cnt;j++) { int tmp=i*prime[j]; if(v[i]<prime[j]||tmp>n) break; v[tmp]=prime[j]; phi[tmp]=phi[i]*(i%prime[j]?prime[j]-1:prime[j]); } } }
3、同餘
(1)同餘的概念:通常的,設n爲正整數,a和b爲整數,若是a和b被n除後餘數相同,那麼稱a和b模n同餘,記做$a≡b$ $(mod$ $n)$
(2)同餘的性質:
- $a≡b$ $(mod$ $n)$ $\Leftrightarrow$ $n|a-b$
- 若$a≡b$ $(mod$ $n)$,且$c≡d$ $(mod$ $n)$, ① $a+c≡b+d$ $(mod$ $n)$ ② $ac≡bd$ $(mod$ $n)$
- ①$ka≡kb$ $(mod$ $n)$ (k爲任意整數) ②若$ab≡ac$ $(mod$ $n)$,設$d=(a,n)$,則$b≡c$ $(mod$ $n/d)$
- $a^m≡b^m$ $(mod$ $n)$ (m爲正整數)
這裏證實一下第三條第二點 $ab≡ac$ $(mod$ $n)$ $d=(a,n)$ $\Rightarrow n | a(b-c)$ $\Rightarrow n/d |a(b-c)/d$ 由$gcd(n/d,a/d)=1$ $\Rightarrow n/d |(b-c)$ $\Rightarrow b≡c(mod n/d)$
(3)一次同餘方程求解(exgcd或者叫大衍求一術):
對於一次同餘方程$ax≡b(mod m)$ $\Rightarrow m|ax-b$ 設$-ym=ax-b$ 即爲$ax+my=b$ 轉化爲求解一元二次不定方程
對$ax+by=d$ 當$gcd(a,b)|d$時,有整數解
證實即求解方法: 由歐幾里得:$gcd(a,b)=gcd(b,r)=...=gcd(a_n,0)$ 使用數學概括法 對最後一步:$a_nx_n+0y_n=a_n$ 顯然對這個方程有解$x_n=1,y_n=0$ 若$a_mx_m+b_my_m=d$有解 則對$a_{m-1}*x_{m-1}+b_{m-1}y_{m-1}=d$ 有$b_{m-1}=a_m,a_{m-1}=\lfloor a_{m-1}/a_m\rfloora_m+b_m$(gcd得出) $\Rightarrow (\lfloor a_{m-1}/a_m\rfloor a_m+b_m)x_{m-1}+a_my_{m-1}=d$ $\Rightarrow (kx_{m-1}+y_{m-1})*a_m+x_{m-1}*b_m=d$ $\Rightarrow x_{m-1}=y_m,y_{m-1}=x_m-\lfloor a_{m-1}/a_m\rfloor *y_m$ 由以上,咱們獲得了它的證實和解法
(4)歐拉定理
若$gcd(a,n)=1$,則有$a^{φ(n)}≡1(mod$ $n)$
證實: 定義簡化剩餘類:把全部與整數a(a與n互質)模n同餘的整數構成的集合叫作模n的一個簡化剩餘類,記做$a[n]$,並把a叫作簡化剩餘類$a[n]$的一個簡化剩餘系。
先證實當集合$x$剛好遍歷(即取遍)$n$每個簡化剩餘系時,$kx$也遍歷。($k$爲任意整數,$gcd(x,n)=1$)
反證:如有$kx_i≡kx_j (mod$ $n)$ 則 $x_i≡x_j (mod$ $n)$ 矛盾,得證
下面歐拉定理: 設${\overline{a_1},\overline{a_2},...,\overline{a_φ(n)}}$是$n$的一個簡化剩餘類 由上${\overline{aa_1},\overline{aa_2},...,\overline{aa_φ(n)}}$也是 則$aa_1aa_2...aa_{φ(n)}≡a_1a_2...a_{φ(n)} (mod$ $n)$ 則$a^{φ(n)}≡1(mod$ $n)$
特別的,當$n$取質數時,有$φ(n)=n-1$ 則$a^{n-1}≡1 (mod$ $n)$,即爲費馬小定理
(5)乘法逆元
對於"+"、"-"、"*",咱們都已經獲得了它在mod p下的轉換式,那麼對於"/"呢?
定義:若整數$b,m$互質,而且$b|a$,則存在一個整數$x$,使得$a/b≡a*x(mod$ $m)$。稱$x$爲$b$的乘法逆元,記爲$b^{-1}≡(mod$ $m)$ 對於這個有解性能夠轉換成一次同餘方程的有解來證實,很少贅述。
求法:$a/b≡ab^{-1}≡a/bbb^{-1}(mod$ $m)$,即$bb^{-1}≡1(mod$ $m)$,即轉換爲同餘方程求解。特別的,當$m$爲質數時,能夠用費馬小定理求解
- $O(n)$求解$1$ ~ $n(mod$ $p)$的逆元 假設$p=ki+r,k<i$,咱們嘗試用$k^{-1}$求$i^{-1}$ $ki+p≡0(mod$ $p)$ $\Rightarrow ki≡-r(mod$ $p)$ $\Rightarrow ki*i^{-1}r^{-1}≡-rr^{-1}i^{-1} (mod$ $p)$ $\Rightarrow -kr^{-1}≡i^{-1} (mod$ $p)$ $\Rightarrow i^{-1}≡-\lfloor p/i \rfloor *(p$ $mod$ $i)^{-1} (mod$ $p)$
其實,這本質上是利用了逆元也是積性函數的性質。 參考代碼:
#include <cstdio> #define ll long long const int N=3000010; ll n,p,inv[N]; int main() { scanf("%lld%lld",&n,&p); inv[1]=1;printf("1\n"); for(int i=2;i<=n;i++) { inv[i]=((inv[p%i]*(p-p/i))+p)%p; printf("%lld\n",inv[i]); } return 0; }
- $O(n)$求解$1!$~$n!$的逆元($p$爲質數) 設第$i$項階乘爲$f_i$,則有$f_i=if_{i-1}$ 若已經求得${f_i}^{-1}$ 則有$i{f_{i-1}}{f_i}^{-1}≡f_{i-1}{f_{i-1}}^{-1} \ (mod \ p)$ 化簡得 $f_{i-1}^{-1}≡i*{f_i}^{-1} \ (mod \ p)$
參考代碼:
void getinv() { inv[0]=1; fac[0]=1; for(int i=1;i<=n;i++) fac[i]=(fac[i-1]*i)%mod; inv[n]=quick_pow(fac[n],n-2); for(int i=n-1;i;i--) inv[i]=(inv[i+1]*(i+1))%mod; }
(6)中國剩餘定理(孫子定理)
求解一次同餘方程組,其中$m_1,m_2,...m_n$兩兩互質 $$\begin{equation} \left{ \begin{aligned} x ≡ b_1 (mod \ m_1) \ x ≡ b_2 (mod \ m_2) \ ... \ x ≡ b_n (mod \ m_n) \ \end{aligned} \right. \end{equation} $$
方法:先找到整數$L_1$,使得$L_1≡1(mod \ m_1),b_1|L_1,b_2|L_1,...,b_n|L_1$ 即$L_1$是同餘方程 $$\begin{equation} \left{ \begin{aligned} x ≡ 1 (mod \ m_1) \ x ≡ 0 (mod \ m_2) \ ... \ x ≡ 0 (mod \ m_n) \ \end{aligned} \right. \end{equation} $$ 的解。
把$L_1$乘上$b_1$,即知足了第一個方程,而其他無影響。
而後找到$L_2,...,L_n$. $x=\prod_{i=1}^n L_i$即爲同餘方程的解。
下面討論如何獲得$L_i$。 令$M=\prod_{i=1}^n m_i$,設$M_i=M/m_i$ 則$M_i$知足整除除了$b_i$的全部$b$
而後咱們要求$L_i≡1(mod \ b_i)$ 設$M_i*t_i≡1(mod \ b_i)$ 即轉換爲了求解一次同餘方程的問題。
咱們對同餘方程組進行$n$次同餘方程的求解便可。
解爲 $x≡\prod_{i=1}^n M_it_ib_i (mod \ M)$
參考代碼:中國剩餘定理
4、組合計數
(1)加法原理與乘法原理
加法原理:作一件事,完成它能夠有$n$類辦法,在第一類辦法中有$m_1$種不一樣的方法,在第二類辦法中有$m_2$種不一樣的方法,……,在第$n$類辦法中有$m_n$種不一樣的方法,那麼完成這件事共有$N=\sum{i=1}^n m_i$種不一樣方法。每一種方法都可以直接達成目標。
乘法原理:作一件事,完成它須要分紅$n$個步驟,作第一步有$m_1$種不一樣的方法,作第二步有$m_2$種不一樣的方法,……,作第$n$步有$m_n$種不一樣的方法,那麼完成這件事共有$N=\prod_{i=1}^n m_i$種不一樣的方法。
(2)排列組合
從$n$個互異元素中依次取出$m$個元素存在順序的排除一列,產生的不一樣排列的數量是 $A_n^m=n*(n-1)(n-2)...*(n-m+1)=\frac{n!}{(n-m)!}$
從$m$個互異元素中取出m個元素組成一個集合不存在順序,產生的不一樣組合的數量是 $C_n^m=\frac{A_n^m}{m!}=\frac{n!}{m!(n-m)!}$
考慮取出$m$個元素會產生$m!$種順序
- 組合數的性質 ①$C_n^m=C_n^{(n-m)}$ 感性證實:從集合中取出了$m$個元素就剩下了$n-m$個元素,方案數是相等的 ②**$C_n^m=C_{n-1}^{m}+C_{n-1}^{m-1}$**(楊輝三角) 這一點十分重要,由此能夠得出組合數的遞推式。 感性證實:如今已經取到了第$n$個元素。咱們有兩個選擇,取第$n$個元素或不取第$n$個元素 若取第$n$個元素,則先在前$n-1$個元素中取$m-1$個,爲$C_{n-1}^{m-1}$ 若不取第$n$個元素,則先在前$n-1$個元素中取$m$個,爲$C_{n-1}^m$ 根據加法原理,能夠獲得$C_n^m=C_{n-1}^{m}+C_{n-1}^{m-1}$ ③$\sum{i=0}^n C_n^i=2^n$ 感性證實:從$n$個互異元素中取出若干個組成一個集合,有$n+1$種方法,分別取出0,1,..n個元素,又由加法原理,有$\sum{i=1}^n$種方法 從另外一種角度看,每一個元素在原集合裏都有兩種狀況,取或不取,方案數爲$2^n$
以上也能夠代入計算式進行驗證。
- 組合數的求法 ①用第二個性質,能夠在$O(n^2)$求出0<=j<=i<=n的全部組合數$C_i^j$
void get() { C[1][1]=1; for(int i=2;i<=N;i++) for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod; }
②用計算式在$O(nlogn)$求出某一個組合數$C_i^j$ 由於結果通常較大,一般會用mod取一下模 因此先求出分母$m!(n-m)!$的逆元
void getinv() { inv[0]=1; fac[0]=1; for(int i=1;i<=n;i++) fac[i]=(fac[i-1]*i)%mod; inv[n]=quick_pow(fac[n],n-2); for(int i=n-1;i;i--) inv[i]=(inv[i+1]*(i+1))%mod; } int get(int i,int j) { return (fac[i]*inv[j]*inv[i-j])%mod; }
(3) 二項式定理
$(x+y)^n=\sum_{i=0}^n C_n^ia^ib^{n-i}$ 這個其實手玩一下就出來了,用排列組合的思想考慮每一項出現的次數。 下面證實$Lucas$定理要用到
(4) $Lucas$ 定理
若$p$是素數,則有 $C_n^m≡C_{n%p}^{m%p}*C_{n/p}^{m/p} \ (mod \ p)$
證實: 首先素數的條件用在這個地方 當$p$爲質數時,任取$x \in (1,p)且x \in N$,知足$C_p^x≡0 \ (mod \ p)$。這點不難,不證實了。
設$n=ap+r_1,m=bp+r_2$
取$(1+x)^n%p$這樣一個式子,咱們對它進行變形(本質上對應將數進行p進制分解)
$(1+x)^n=(1+x)^{ap+r_1}=((1+x)^p)^a*(1+x)^{r_1}$ $≡(1+x^p)^a*(1+x)^{r_1}=\sum_{i=0}^a C_a^ix^{ip}\sum C_{r_1=0}^jx^j \ (mod \ p)$(注意最後兩步用了二項式定理化簡,第三步用了那個沒證實的玩意兒)
整理得$(1+x)^n≡\sum_{i=0}^a C_a^ix^{ip}\sum C_{r_1=0}^jx^j \ (mod \ p)$
對左邊這樣一項$x^{bp+r_2}$來講,它的係數爲$C_{ap+r_1}^{bq+r_2}$
而右邊當且僅當$i=b,j=r_2$時,能夠構成這個項,而它的係數爲$C_a^b*C_{r_1}^{r_2}$
即$C_n^m≡C_{n%p}^{m%p}*C_{n/p}^{m/p} \ (mod \ p)$,則得證
咕咕咕
開始更新組合數學 2018.6.29