四、组合数学
Prufer序列
long long fa[N], prufer[N], d[N];
long long n, m, ans;
void get_Prufer () {
long long p = 1 , tot = 0 ;
for (long long i = 1 ; i <= n - 1 ; i ++)
d[fa[i]] ++, d[i] ++;
for (long long i = 1 , p = 1 ; i <= n; p = ++ i)
while (d[p] == 1 && p <= i && tot + 1 <= n - 2 )
prufer[++ tot] = fa[p], d[fa[p]] --, p = fa[p];
return ;
}
void get_Tree () {
long long root = n;
for (long long i = 1 ; i <= n - 2 ; i ++)
d[prufer[i]] ++;
for (long long i = 1 ; i <= n; i ++)
d[i] ++, fa[i] = root;
long long cnt = 0 ;
for (long long i = 1 , p = 1 ; i <= n; p = ++ i)
while (d[p] == 1 && p <= i && cnt + 1 <= n - 2 )
fa[p] = prufer[++ cnt], d[prufer[cnt]] --, p = fa[p];
}
范德蒙德卷积
\(\sum_{i = 0} ^ k {{n} \choose{i}}{{m}\choose{k - i}} = {{n + m}\choose k}\)
可以理解为在大小为n和m的两个堆中选择k个物品
推论:
\(\sum _{i = -r} ^ s {n\choose r + i} {m \choose s - i} = {{n + m} \choose {r + s}}\)
\(\sum_{i = 1} ^ n {n \choose i}{n\choose {i - 1}} = {{2n} \choose {n - 1}}\)
\(\sum_{i = 0} ^ n {n \choose i} ^ 2 = {{2n} \choose n}\)
\(\sum_{i = 0}^m{n \choose i}{m \choose i} = \sum_{i =0} ^ m{n\choose i}{m \choose {m - i}} = {{n +m} \choose m}\)
二项式反演
\[F(n) = \sum_{i=0}^n{(-1)^i {{n}\choose i}} G(i) \ \ ⟺ \ \
G(n) = \sum_{i=0}^n{(-1)^i {{n}\choose i}} F(i)
\\
F(n) = \sum_{i=0}^n{{{n}\choose i}} G(i) \ \ ⟺ \ \
G(n) = \sum_{i=0}^n{(-1)^{i-n} {{n}\choose i}} F(i)
\\
F(n) = \sum_{i=n} {(-1)^i {{i}\choose n}} G(i) \ \ ⟺ \ \
G(n) = \sum_{i=n} {(-1)^i {{i}\choose n}} F(i)
\\
F(n) = \sum_{i=n} {{{i}\choose n}} G(i) \ \ ⟺ \ \
G(n) = \sum_{i=n} {(-1)^{i-n} {{i}\choose n}} F(i)
\]
单位根反演
\[[n|a]\ = \ {\frac{1}{n} \sum_{k = 0} ^{n -1} w^{ak}_n}
\\
[a=b \ ( \% n)] = [a - b = 0 \ (\% n)] =
{\frac{1}{n} \sum_{k = 0} ^{n -1} w^{(a-b)k}_n} =
{\frac{1}{n} \sum_{k = 0} ^{n -1} w^{ak}_nw_n^{-bk}}
\]
\(w_n^k\) 是\(x^n=1\) 的第k个复数解,等于\(w_n\) 的k次方
min-max容斥
\[max(S) =\sum_{T \subseteq S}) ^ {|T| + 1}min(T)
\\
min(S) =\sum_{T \subseteq S}) ^ {|T| + 1}max(T)
\\
E(max(S)) =\sum_{T \subseteq S}) ^ {|T| + 1}E(min(T))
\\
E(min(S)) =\sum_{T \subseteq S}) ^ {|T| + 1}E(max(T))
\]
卡特兰数
\[Cat_n = \frac{2n \choose n}{n + 1} = {2n \choose n} - {2n \choose {n-1}}
\]
\[Cat_1 = 1, Cat_n = Cat_{n - 1} \frac{4n-2}{n + 1}
\]
\[Cat_n = \begin{cases} \sum_{i=1}^n Cat_{i-1} Cat_{n-i} & n \geq2, n\in N_+ \\
1 & n = 0, 1
\end{cases}
\]
\[Cat_n = \frac{Cat_{n-1}(4n-2)}{n+1}
\]
生成函数
\[Cat(x) = 1 + x * Cat^2(x)
\\
Cat(x) = \frac{1 - \sqrt{1 - 4x}}{2x}
\]
斯特林数
第二类斯特林数·列
poly::vec ask[N << 1 ];
void part (int p, int l, int r) {
if (l == r){
ask[p].resize(2 );
ask[p][0 ] = 1 ;
ask[p][1 ] = mod - l;
return ;
}
int mid = l + r >> 1 ;
part(p << 1 , l, mid);
part(p << 1 | 1 , mid + 1 , r);
ask[p] = poly::Multiply(ask[p << 1 ], ask[p << 1 | 1 ]);
}
void work () {
using namespace poly;
int n, k;
cin >> n >> k;
part(1 , 1 , k);
ask[1 ] = GetInv(n + 1 , ask[1 ]);
for (int i = 0 ; i <= k - 1 ; i ++)
printf ("0 " );
for (int i = k; i <= n; i ++)
printf ("%d " , ask[1 ][i - k]);
}
\[H(n) = \frac{x^n}{\prod_i(1 - ix)}
\\
\sum_{n = k} ^ \infty S_2(n, k) \frac{x^n}{n!} = \frac
{(e^x - 1)^k}{k!}
\]
第二类斯特林数·行
\[S_2(n, m) = \sum _{i = 0} ^m \frac{i^n}{i!} \frac{(-1)^{m - i}}{(m - i)!}
\\
n^m = \sum_{i = 0}^n {n\choose i}i!S_2(m,i)
\\
S_2(m, n)n! = \sum_{i = 0} ^ n {(-1)}^{n - i}{n\choose i}i^m
\\
S_2(n+1, m+1) = \sum_k{n\choose k}S_2(k,m) = \sum_{k=0}^n S_2(k,m)(m+1)^{n-k}
\]
第一类斯特林数
\[S_1 (n, m) = S_1(n - 1, m - 1) + (n - 1)S_1(n - 1, m)
\]
\[S_1(n,1) = (n-1) !
\\
S_1(n,2) = (n-1)!H_{n-1}
\\
S_1(n,n) = 1
\\
S_1(n,k) \geq S_2(n,k)
\]
\[S_2(n, n-1) = S_1(n, n-1) = {n \choose 2}
\]
\[\sum_{k=0}^n S_1(n,k) = n!
\]
\(S_1(n, i)\) 的生成函数
\[\sum _{i = 0}^{n - 1} (s +i)
\]
分治+NTT\(O(nlognlogn)\)
斯特林反演
\[f(n) = \sum_{i = 0}^n S_2(n, i)g(i)
\\
g(n) = \sum_{i = 0}^n(-1)^{n - i} S_1(n,i)f(i)
\]
多项式转下降幂
\[\sum_{i=0}^j\frac {a_i}{j!} \sum_{k=0} ^ j (-1) ^{j-k} * \sum _{i=0}^{n-1} \frac{a_ik^i}{k!}
\\
f_k = \frac {a_i}{j!}
\ \ \ g_k = \sum _{i=0}^{n-1} \frac{a_ik^i}{k!} \ (使用多点求值)
\\
a' = f*g
\]
贝尔数
\[B_{n + 1} = \sum^n_{k = 0} {n \choose k} B_k
\\
B_{p + n} \equiv B_n + B_{n + 1} (mod\ p) \ \ (p\ is\ a\ prime)
\\
\sum _{n = 0} ^ \infty \frac{B_n}{n!} x^n = e^{e^x -1}
\]
拆分数
把{1,2,3......n} 分成S = {1,2......T}和B = {T+1,T+2......n};
\[Ans = \sum_{i=0}^n ans_S[i] * ans_T[n - i]
\]
对于S:\(dp_{i,j}\) 表示组成i最大为j的方案数
\(dp_{i,j} \ =\ \sum _{k = 0} ^ j dp_{i-j,k}\ = \ \sum_{k=0} ^ {j-1}dp_{i-j,k} + dp_{i-j,j} \ = \ dp_{i-1,j-1} + dp_{i-j,j}\)
对于T:\(dp_{i,j}\) 表示组成i用了j个数的方案数
\(dp_{i,j} = dp_{i-T-1,j - 1} + dp_{i-j,j}\)
\(dp_{i-T-1,j - 1}\) :i中最小的数为(T+1)
\(dp_{i-j,j}\) : i中最小的数不为T+1,将这j个数-1
欧拉数
\[Eular(n, k) = \sum _{x = k} ^n (-1)^{n - x}(x - k) ^ n \frac{(n + 1) ! }{(x + 1) ! (n - x)!}
\]
\(n^2的dp:\) dp[i][j]: i 的排列中,有j个小于号的方案数
\[dp[i][0] = 1
\\
dp[i][j] \ =\ dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1)
\]
\[m!S_2(n,m) = \sum_{k=0}^nEular(n,k){ k\choose n-m}
\\
x^n = \sum_{k=0}^n Eular(n,k){x+k\choose n}
\]
常用生成函数
卡特兰生成函数
\[C(x) = \frac{ \sqrt{1 - 4x}}{2x} = \sum^{\infty}_{i=0}
{\frac{2i \choose i}{i+1}}x^i
\]
斐波拉契生成函数
\[F(x) = xF(x) + x^2F(x) - f_0x + f_1x + f_0
\\
F(x) = \frac{x}{1 - x - x^2}
\]
欧拉变换
\[Eular(F(x)) = \prod_i \frac{1}{(1 - x^i) ^{f_i}}
\]
类似于EGF中的exp变换
\[exp(F(x)) = \sum_i \frac{F^i(x)}{i!}
\]
EGF 的\(exp\) 具有的组合意义是:将\(1\sim n\) 分成若干非空 组,大小为 的\(f_i\) 组内部具有 中方\(f_i\) 案,问最后的总方案数。
而 Euler 变换就是去除了这个标号 的方案数,去掉标号会导致「如果两个组大小和内部方案均相同 ,则它们不可区分」。
因此 Euler 的第一个定义式就易懂了。(即大小为 ii 的每种内部方案都可以选若干个,每种内部方案的生成函数都是\((1 - x^i) ^{-1}\)
现在有两种方法可以得到Euler 变换的第二个定义式:
\[Eular(F(x)) = exp(\sum_i \ln \frac{1}{(1 - x^i)^{f_i}})
\\
= exp(\sum_i - f_i \ln (1 - x^i))
\\
= exp(\sum_i f_i\sum_j \frac{x^{ij}}{j})
\\
= exp(\sum _j \frac{F(x^j)}{j})
\]
*2022/10/5 新增范德蒙德卷积及推论
*2022/11/24 新增普通多项式转下降幂多项式
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本