組合基礎與數論基礎
組合數
Lucas 定理
證明:
引理:\(\forall p\in\mathbb{P},n\in[1,p-1]\cap\mathbb{Z},\binom{p}{n} \equiv 0 \pmod{p}\)
\(\because p\in\mathbb{P},\therefore\binom{p}{x}\equiv\frac{p!}{x!(p-x)!}\equiv p \cdot \frac{(p-1)!}{x!(p-x)!} \equiv 0 \pmod p\)。證畢。
有 \((1+x)^p\equiv\sum\limits_{i=0}^{p}{\binom{p}{i}x^i}\equiv 1+\sum\limits_{i=1}^{p-1}{\binom{p}{i}x^i}+x^p\equiv{1+x^p}\pmod p\)。
設 \(\begin{cases} q_n = \lfloor\frac{n}{p}\rfloor \\ r_n = n \bmod p \\ q_m = \lfloor\frac{m}{p}\rfloor \\ r_m = m \bmod p \end{cases}\),由取模定義可知 \(\begin{cases} q_np+r_n=n \\ q_mp+r_m=m \\ \end{cases}\)。
又 \((1+x)^n=\sum\limits_{i=0}^{n}{\binom{n}{i}x^i}\)
所以 \(\sum\limits_{i=0}^{n}{\binom{n}{i}x^i} \equiv \sum\limits_{i=0}^{q_n}\sum\limits_{j=0}^{r_n}{\binom{q_n}{i}\binom{r_n}{j}x^{ip+j}} \pmod p\)
設 \(k = i \cdot p + j\),因為 \(0 \leq j < r_n\),所以 \(i = \lfloor\frac{k}{p}\rfloor, j = k \bmod p\)
則 \(\sum\limits_{i=0}^{n}{\binom{n}{i}x^i} \equiv \sum\limits_{i=0}^{q_n}\sum\limits_{j=0}^{r_n}{\binom{q_n}{\lfloor\frac{k}{p}\rfloor}\binom{r_n}{k \bmod p}x^{k}} \pmod p\)
因為 \(n\geq m\),則對於左式有 \(i=m\) 時,右式有 \(k=m\) 時,即有 \(\binom{n}{m}x^m\equiv\binom{q_n}{\lfloor\frac{m}{p}\rfloor}\binom{r_n}{m \bmod p}x^m \pmod p\),因為 \(\begin{cases}q_n = \lfloor\frac{n}{p}\rfloor \\ r_n = n \bmod p\end{cases}\),即得 \(\binom{n}{m}\equiv\binom{\lfloor\frac{n}{p}\rfloor}{\lfloor\frac{m}{p}\rfloor}\binom{n \bmod p}{m \bmod p}\pmod p\)。證畢。
擴充套件Lucas exLucas
給定正整數 \(n,m,P,1\leq m \leq n \leq 10^{18},1\leq P \leq 10^6\),求
\(\text{exLucas}\) 和 \(\text{Lucas}\) 定理並無多大關係,\(\text{exLucas}\) 我認為是一種演算法。
學習 \(\text{exLucas}\) 之前建議看看階乘質因數分解。
\(P\) 不為質數,將 \(P\) 質因數分解 \(P = \prod\limits{p_i^{c_i}}\)。
將 \(\binom{n}{m}\) 對每個 \(p^c\) 取模,得出若干同餘方程,利用中國剩餘定理求出答案:
\(\begin{cases} \binom{n}{m} \equiv a_1 \pmod {p_1^{c_1}} \\ \binom{n}{m} \equiv a_1 \pmod {p_1^{c_1}} \\ \binom{n}{m} \equiv a_1 \pmod {p_1^{c_1}} \\ \cdots \\ \binom{n}{m} \equiv a_1 \pmod {p_{w}^{c_{w}}} \\ \end{cases}\)
關鍵在於計算 \(\binom{n}{m} \bmod {p^c}\)。
\(\binom{n}{m} = \frac{n!}{m!(n-m)!} \pmod {p^c}\)
有除法,但是 \(m!(n-m)!\) 不一定和 \(p^c\) 互質,即可能無法求出其逆元。
一個方法是將 \(m!(n-m)!\) 的因子 \(p\) 都除去,使之與 \(p^c\) 互質:
\(\frac{n!}{m!(n-m)!} \equiv \frac{\frac{n!}{p^x}}{\frac{m!}{p^y} \cdot \frac{(n-m)!}{p^z}} \cdot p^{x-y-z}\),\(x\) 就是 \(n!\) 質因數分解後 \(p\) 的指數,\(y,z\) 同理。
\(n! = 1 \times 2 \times 3 \times \dots \times n\) 這 \(n\) 個數當中有 \(\lfloor\frac{n}{p}\rfloor\) 個數是 \(p\) 的倍數,因為每 \(p\) 個數就有一個數是 \(p\) 的倍數。
則 \(n! = \lfloor\frac{n}{p}\rfloor! \cdot p \cdot \prod\limits_{\substack{1\leq i\leq n\\ p\nmid i}}{i}\),\(\lfloor\frac{n}{p}\rfloor!\) 裡可能有 \(p\) 的倍數,可以遞迴地來求。
設 \(f(n) = \frac{n!}{p^x} \bmod p^c\),有 \(f(n) = f(\lfloor\frac{n}{p}\rfloor) \cdot \prod\limits_{\substack{1\leq i\leq n\\ p\nmid i}}{i} \bmod p^c\),沒有 \(\times p\) 的原因是分母是 \(p^x\),\(p\) 都被約掉了。
發現 \(i \cdot p^c + j \equiv j \pmod {p^c}\)
則
則
呼叫一次 \(f\) 的時間複雜度為 \(O(\) 遞迴次數 \(\times(\) 積式 \(+\) 快速冪 \())=O(\log_pn \cdot (p^c + \log_2\lfloor\frac{n}{p^c}\rfloor)) = O(p^c\log + \log^2)\)
現在問題在於求 \(x,y,z\)。
設 \(g(n)=x\),有 \(g(n)=g(\lfloor\frac{n}{p}\rfloor) + \lfloor\frac{n}{p}\rfloor\)。
\(n! = 1 \times 2 \times 3 \times \cdots \times n\),這 \(n\) 個數中是 \(p\) 的倍數顯然有 \(\lfloor\frac{n}{p}\rfloor\) 個,將這 \(\lfloor\frac{n}{p}\rfloor\) 個數 \(\times \frac{1}{p}\) 在相乘可得 \(\lfloor\frac{n}{p}\rfloor!\),即 \(g(\lfloor\frac{n}{p}\rfloor)\),所以 \(g(n)=g(\lfloor\frac{n}{p}\rfloor) + \lfloor\frac{n}{p}\rfloor\)。
綜上,\(\text{exLucas}\) 有以下步驟:
-
質因數分解 \(P = \prod\limits{p_i^{c_i}}\),時間複雜度 \(O(\sqrt{P})\),但是有效 \(p_i^{c_i}\) 最多有 \(O(7)\)
-
計算 \(\binom{n}{m} \bmod p_i^{c_i}\),時間複雜度 \(O(p^c\log + \log^2)\)
\(\binom{n}{m} = \frac{\frac{n!}{p^x}}{\frac{m!}{p^y}\frac{(n-m)!}{p^z}}\cdot p^{x-y-z} \equiv f(n) \cdot f(m)^{-1} \cdot f(n-m)^{-1} \cdot p^{g(n)-g(m)-g(n-m)} \pmod{p^c}\)
-
用中國剩餘定理求出方程組的解,即為答案。時間複雜度 \(O(7 \cdot \log n)\)
步驟 2. 的 \(p^c\) 最壞為 \(P\)。
關於 1. 3. 時間複雜度為什麼和 \(7\) 有關,因為方程的個數即為 \(P\) 不同質因數的個數,最壞情況為 \(P = 2 \times 3 \times 5 \times 7 \times 11 \times 13 \times 17\),\(2 \times 3 \times 5 \times 7 \times 11 \times 13 \times 17 \times 19 > 10^6\)。
1.2. 是巢狀關係,1.2. 執行完執行 3. ,則總時間複雜度為 \(O(\sqrt{P} + 7 \cdot (P\log + \log^2) + 7\log n) = O(\sqrt{P} + P\log)\)。
例題 SDOI2010古代豬文
Luogu SDIO2010古代豬文
給定整數 \(q,n\),\(1\leq q,n \leq 10^9\),計算
若 \(q=999911659\),則答案為 \(0\)。
若 \(q\neq 999911659\),根據尤拉定理推論有:\(q^{\sum_{d|n}{C^{d}_{n}}}\equiv q^{\sum_{d|n}{C^{d}_{n}}\bmod 999911658}\pmod {999911659}\)。
關鍵在於計算 \(\sum_{d|n}{C^{d}_{n}}\bmod 999911658\),模數不是質數,不能應用 \(\text{Lucas}\) 定理,嘗試將其質因數分解。
\(999911658 = 2 \times 3 \times 4679 \times 35617\),這樣的數為 \(\text{square-free-number}\),它的所有質因子質數都是 \(1\)。設 \(x = C^{d}_{n}\),用這四個質因數分別運用 \(text{Lucas}\) 定理給 \(x\) 取模,可得:
\(\begin{cases} x\equiv a_1 \pmod 2 \\ x\equiv a_2 \pmod 3 \\ x\equiv a_3 \pmod {4679} \\ x\equiv a_4 \pmod {35617} \\ \end{cases}\)
用中國剩餘定理求出 \(x\),然後用快速冪求出 \(q^{\sum{x}}\bmod 999911658\),即可。
時間複雜度為 \(O(\)快速冪 \(+\) 求因數 \(\times(\text{Lucas}\) 定理 \(+\) 中國剩餘定理\())=O(\log+\sqrt{n}(\log+\log))=O(\sqrt{n}\log)\)。
求法
求 \(\binom{n}{m} \bmod p, p\in\mathbb{P}\)
方法 \(1\):
透過 \(\binom{n}{m} = \binom{n - 1}{m} + \binom{n - 1}{m - 1}\) 求組合數,時間複雜度 \(O(n^2)\),回答時間複雜度 \(O(1)\)。
方法 \(2\):
預處理 \(0\sim n\) 的階乘和階乘的逆元,時間複雜度 \(O(n)\),回答時間複雜度 \(O(1)\)。
方法 \(3\):
利用 \(\text{Lucas}\) 定理,預處理 \(0\sim p-1\) 的階乘和階乘的逆元,時間複雜度 \(O(p)\),回答時間複雜度 \(O(log_p(n))\)。
方法 \(4\):
求 \(\binom{n}{m}, n\leq 5000, m\leq 5000, n\geq m\)。
注意,沒有取模,需要用到高精度。
利用 \(\binom{n}{m} = \binom{n - 1}{m} + \binom{n - 1}{m - 1}\) \(O(n^2)\) 做貌似可以,但是要用到高精度,還有 \(O(n)\) 的位數,則時間複雜度 \(O(n^3)\)。
唯一分解即質因數分解
根據定義式 \(\binom{n}{m} = \frac{n!}{m!(n-m)!}\) 來做,又因為組合數一定是個整數,所以我們用不到高精度除法,對分子和分母唯一分解,分子的每個質數的指數一定大於等於分母的對應指數,若小於則 \(m!(n-m)!\) 不整除 \(n!\),與組合數是整數矛盾。
綜上步驟為:
- 對 \(n!,m!,(n-m)!\) 唯一分解。
- 約分,即用 \((n-m)!,m!\) 唯一分解出的質數消 \(n!\) 唯一分解出的質數。
- 高精度 \(\times\) 低精度
對 \(x!\) 質因數分解
程式碼實現:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 5010;
int primes[N], cnt;
int sum[N];
bool st[N];
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; primes[j] <= n / i; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
int get(int n, int p) // 求n!中 質因子 p 需要累乘的次數
{
int res = 0;
while (n)
{
res += n / p;
n /= p;
}
return res;
}
vector<int> mul(vector<int> a, int b)
{
vector<int> c;
int t = 0;
for (int i = 0; i < a.size(); i ++ )
{
t += a[i] * b;
c.push_back(t % 10);
t /= 10;
}
while (t)
{
c.push_back(t % 10);
t /= 10;
}
return c;
}
int main()
{
int a, b;
cin >> a >> b;
get_primes(a);//用尤拉篩篩出 [1~a] 範圍內的質數
for (int i = 0; i < cnt; i ++ )
{
int p = primes[i];
sum[i] = get(a, p) - get(a - b, p) - get(b, p); // C(a,b) 中第 i 個質數需要累乘的次數
}
vector<int> res;
res.push_back(1);
for (int i = 0; i < cnt; i ++ ) // 列舉質因子
for (int j = 0; j < sum[i]; j ++ ) // 列舉當前質因子的個數
res = mul(res, primes[i]); // 做高精度乘低精度
for (int i = res.size() - 1; i >= 0; i -- ) printf("%d", res[i]);
puts("");
return 0;
}
一些基本式子
式子1
證明:由定義即可得。
它的組合意義是從 \(n\) 個數中選 \(m\) 個數,與從 \(n\) 個數中選 \(n-m\) 個數的方案數相同,相當於剩下 \(n-m\) 個數不選。
式子2
證明:由定義即可得。
它的組合意義是 從 \(n\) 個數中選 \(m\) 個數的方案數 = 已經考慮了前 \(n - 1\) 個數,選擇當前數的方案數(\(\binom{n-1}{m-1}\)) + 不選當前數的方案數 (\(\binom{n-1}{m}\))
它滿足楊輝三角(帕斯卡三角)。
它可以看做一個遞推式。
式子3
證明:由定義即可得。
式子4 二項式定理
證明:
證法1:
數學歸納法。當 \(n = 0\) 時,\((x+y)^0=1=\sum\limits_{i=0}^{0}\binom{0}{i}x^iy^{0-i}\),成立。
當 \(n=m\) 成立,現在證明 \(n=m+1\) 時成立:
證畢。
由二項式定理可以得出許多有用的式子:
-
\(\sum\limits_{i=0}^{n}\binom{n}{i}=2^n\)
證明:將 \((1+1)^n\) 二項式展開即得。
它的組合意義是,從 \(n\) 個數中選若干個數的方案數 = 從 \(n\) 個數中選 \(0\) 個數的方案數 + 從 \(n\) 個數中選 \(1\) 個數的方案數 + ... + 從 \(n\) 個數中選 \(n\) 個數的方案數。
-
\(\sum\limits_{i=0}^{n}(-1)^i\binom{n}{i} = 0\)
證明:將 \(((-1)+1)^n\) 二項式展開即得。
式子4
證明:
證畢。
不定方程整數解問題
問題1
隔板法。
考慮有 \(m\) 個點,放入 \(n - 1\) 個隔板,將 \(m\) 個點分成 \(n\) 組點,每組點的個數為 \(x_i\) 的值。
例如:\(m=10,n=3\),有一種方案是:.|.......|..,這代表 \(x_1=1,x_2=7,x_3=2\)。
隔板顯然不能放最左邊和最右邊,則 \(m\) 個點總共有 \(m-1\) 個空可供 \(n-1\) 個隔板放置,答案即為 \(\binom{m-1}{n-1}\)。
問題2
考慮轉換成問題1。換元 \(y_i=x_i-a_i+1\),原問題轉化為求 \(y_i\geq 1,y_1+y_2+y_3+\cdots+y_n=m+\sum(-a_i+1)\)的正整數解方案數,答案即為 \(\binom{m+\sum(-a_i+1)-1}{n-1}\)
問題3
新添一個數 \(x_{n+1},x_{n+1} = m - \sum\limits_{1\leq i\leq n} x_i\),\(x_i\) 沒用完的都給 \(x_{n+1}\),原問題轉化為求 \(x_i\geq 1,x_1+x_2+x_3+\cdots+x_n+x_{n+1}\leq m\) 的正整數方案數,答案即為 \(\binom{m - 1}{n}\)。
問題4
拆成兩個問題:
- 求 \(x_i\geq 1,x_1+x_2+x_3+\cdots+x_n\leq l-1\) 正整數解方案數
- 求 \(x_i\geq 1,x_1+x_2+x_3+\cdots+x_n\leq r\) 正整數解方案數
2.的方案數 - 1.的方案數即為答案。
卡特蘭數 Catalan
給定 \(n\) 個 \(0\) 和 \(n\) 個 \(1\),按某種順序排成長度為 \(2n\) 的序列,滿足任意字首中 \(0\) 的個數都不少於 \(1\) 的個數的序列的數量為:
證明:\(Cat_n = \frac{\binom{2n}{n}}{n+1}\)
令 \(n\) 個 \(0\) 和 \(n\) 個 \(1\) 隨意排列成一個長度為 \(2n\) 的序列 \(S\),若 \(S\) 不滿足任意字首中 \(0\) 的個數都不小於 \(1\) 的個數,則存在一個最小的位置 \(2p+1\in[1,2n]\cap\mathbb{Z}\),使得 \(S[1\sim 2p+1]\) 中有 \(p\) 個 \(0\)、\(p+1\) 個 \(1\)。把 \(S[2p+2\sim2n]\) 中所有數字取反後,包含 \(n-p-1\) 個 \(0\)、\(n-p\) 個 \(1\)。於是我們得到了由 \(n-1\) 個 \(0\) 和 \(n+1\) 個 \(1\) 排成的、存在一個字首 \(0\) 比 \(1\) 多的序列。
同理。令 \(n-1\) 個 \(0\) 和 \(n+1\) 個 \(1\) 隨意排列成一個長度為 \(2n\) 的序列 \(S\),存在一個最小的位置 \(2p+1\in[1,2n]\cap\mathbb{Z}\),使得 \(S[1\sim 2p+1]\) 中有 \(p\) 個 \(0\)、\(p+1\) 個 \(1\)。把 \(S[2p+2\sim2n]\) 中所有數字取反後,我們得到了由 \(n\) 個 \(0\) 和 \(n\) 個 \(1\) 排成的、存在一個字首 \(0\) 比 \(1\) 多的序列。
因此,以下兩種序列構成一個雙射:
- 由 \(n\) 個 \(0\)、\(n\) 個 \(1\) 排成的、存在一個字首 \(0\) 比 \(1\) 多的序列。
- 由 \(n-1\) 個 \(0\)、\(n+1\) 個 \(1\) 排成的序列。
後者顯然有 \(\binom{2n}{n-1}\) 個。
綜上,由 \(n\) 個 \(0\) 和 \(n\) 個 \(1\),按某種順序排成長度為 \(2n\) 的序列,滿足任意字首中 \(0\) 的個數都不少於 \(1\) 的個數的序列的數量為:
證畢。(此證明摘自李煜東《演算法競賽進階指南》)
證明:\(Cat_n = \sum\limits_{i=1}^n{Cat_{i-1} \cdot Cat_{n-i+1}},Cat_0=1\)
考慮序列 \(1,2,3,...,n\) 經過一個棧的合法出棧的方案數 \(f_n\)。
將進棧操作看做 \(0\), 出棧操作看做 \(1\),則 \(f_n = Cat_n\)。
對於當前數字 \(i\),\(1\sim i-1\) 有 \(f_{i-1}\) 進出棧方案,\(i+1\sim n\) 有 \(f_{n-i+1}\) 種進出棧方案,所以共有 \(f_{i-1}\cdot f_{n-i+1}\) 種方案。對於所有數字有 \(f_n=\sum\limits_{i=1}^n{f_{i-1}\cdot f_{n-i+1}}\) 種方案。
綜上 \(Cat_n = \sum\limits_{i=1}^n{f_{i-1}\cdot f_{n-i+1}}\)。
證畢。
與卡特蘭數有關的問題
\(n\) 個左括號和 \(n\) 個右括號組成的合法括號序列的數量為 \(Cat_n\)。
證明:將左括號看做 \(0\),將右括號看做 \(1\) 即得。
\(n\) 個節點構成不同的二叉樹的數量為 \(Cat_n\)。
證明:設\(n\) 個節點構成不同的二叉樹的數量為 \(f_n\),對於當前的節點 \(i\),\(1\sim i-1\) 節點放置的方案數為 \(f_{i-1}\),\(i+1\sim n\) 節點放置的方案數為 \(f_{n-i+1}\),則 \(f_n = \sum\limits_{i=1}^{n}{f_{i-1}\cdot f_{n-i+1}}\),符合 \(Cat_n\),的式子。
在平面直角座標系中,從 \((0,0)\) 開始,每一步只能向上或向右走,走到 \((n, n)\) 並且除兩個端點外不接觸直線 \(y=x\) 的路線數量為 \(2Cat_{n-1}\)。
證明:
第一步只能向上或向右走,就變成了兩個本質相同的問題,所以答案 \(\times2\)。
現在考慮第一步向右走,即從 \((1,0)\) 點開始。設走一步的操作為 U、R,U 代表向上,R 代表向右,最後走到 \((n,n)\) 點的操作一定形如 RRUURRU...,由 \(n-1\) 個 U 和 \(n-1\) 個 R 組成的串。為了不接觸直線 \(y=x\),操作一定滿足任意字首 R 的數量大於等於 U 的數量。將 R 看做 \(0\),U 看做 \(1\),答案即為 \(Cat_{n-1}\)。
容斥原理
摩根定律
記 \(\overline{A}\) 為以 \(S\) 為全集 \(A\) 的補集。
容斥原理
例如 \(|A\cup B| = |A| + |B| - |A\cap B|\),\(|A\cup B\cup C| = |A| + |B| + |C| - |A\cap B| - |A\cap C| - |B\cap C| + |A\cap B\cap C|\)
多重集組合數
特殊情況
設 \(S = \{n_1 \cdot a_1, n_2 \cdot a_2, \cdots, n_k \cdot a_k\}\) 是由 \(n_1\) 個 \(a_1\)、\(n_2\) 個 \(a_2\)、\(\cdots\)、\(n_k\) 個 \(a_k\) 組成的多重集。給定非負整數 \(r\),\(\forall i,r \leq n_i\)。從 \(S\) 中取出 \(r\) 個元素組成一個多重集(不考慮元素的順序),可得的不同多重集的數量為:
證明:
考慮不定方程。
設選了 \(x_i\) 個 \(a_i\),則有方程 \(\sum\limits_{1\leq i\leq k}x_i =r,0 \leq x_i \leq n_i\),因為 \(r\leq n_i\),則一定滿足 \(x_i \leq n_i\)。原問題變成 \(\sum\limits_{1\leq i\leq k}x_i =r,0 \leq x_i\) 的正整數解,這是不定方程整數解問題2,答案即為 \(\binom{k+r-1}{k-1}\),證畢。
一般情況
設 \(S = \{n_1 \cdot a_1, n_2 \cdot a_2, \cdots, n_k \cdot a_k\}\) 是由 \(n_1\) 個 \(a_1\)、\(n_2\) 個 \(a_2\)、\(\cdots\)、\(n_k\) 個 \(a_k\) 組成的多重集。給定非負整數 \(r\)。從 \(S\) 中取出 \(r\) 個元素組成一個多重集(不考慮元素的順序),可得的不同多重集的數量為:
即
證明:
考慮不定方程。
設選了 \(x_i\) 個 \(a_i\),則有方程 \(\sum\limits_{1\leq i\leq k}x_i =r,0 \leq x_i \leq n_i\)。
先不考慮 \(x_i \leq n_i\) 的限制,\(0\leq x_i\) 的方案數為 \(\binom{k-1}{k+r-1}\),然後再減去不合法的方案。
不合法的方案為 \(\exists x_i,x_i\geq n_i\)的方案。於求不合法的方案:
設 \(x_a \geq n_a\),則限制變為 \(x_a \geq n_a, 0\leq x_i, (i\neq a)\),這是不定方程整數解問題2,答案即為 \(\binom{k+r-n_a-2}{k - 1}\)。
設 \(a\neq b,x_a \geq n_a, x_b \geq n_b\),則限制變為 \(x_a \geq n_a,x_b\geq n_b, 0\leq x_i, (i\neq a,i\neq b)\),這是不定方程整數解問題2,答案即為 \(\binom{k+r-n_a-n_b-3}{k - 1}\)。上一種包含含這種情況,所以要減去。
以此容斥。
最中得到 \(\binom{k-1}{k+r-1} - \sum\limits_{\emptyset\neq S\subseteq\{1,2,3,\dots,k\}}{(-1)^{|S|+1}\binom{k+r-\sum\limits_{i\in S}{n_i}- |S| -1}{k-1}}\)。
證畢。