算法数学笔记-四、组合数学
四、组合数学
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];
}
二项式反演
单位根反演
\(w_n^k\)是\(x^n=1\)的第k个复数解,等于\(w_n\)的k次方
min-max容斥
卡特兰数
\(Cat_n = \frac{C^n_{2n}}{n + 1}\)
\(Cat_1 = 1, Cat_n = Cat_{n - 1} \frac{4n-2}{n + 1}\)
斯特林数
第二类斯特林数·列
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]);
}
第二类斯特林数·列
第一类斯特林数
\(S_1(n, i)\)的生成函数
分治+NTT\(O(nlognlogn)\)
斯特林反演
贝尔数
拆分数
把{1,2,3......n} 分成S = {1,2......T}和B = {T+1,T+2......n};
对于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
欧拉数
\(n^2的dp:\) dp[i][j]: i 的排列中,有j个小于号的方案数
常用生成函数
卡特兰生成函数
斐波拉契生成函数
欧拉变换
类似于EGF中的exp变换
EGF 的\(exp\)具有的组合意义是:将\(1\sim n\)分成若干非空组,大小为 的\(f_i\)组内部具有 中方\(f_i\)案,问最后的总方案数。
而 Euler 变换就是去除了这个标号的方案数,去掉标号会导致「如果两个组大小和内部方案均相同,则它们不可区分」。
因此 \text{Euler}Euler 的第一个定义式就易懂了。(即大小为 ii 的每种内部方案都可以选若干个,每种内部方案的生成函数都是\((1 - x^i) ^{-1}\)
现在有两种方法可以得到Euler 变换的第二个定义式:
原文地址:https://www.cnblogs.com/lyhy/p/16743081.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android自定义View实现炫酷进度条
- OpenSSL的VC编程 - MD5
- 详解AndroidStudio中代码重构菜单Refactor功能
- Android自定义View仿QQ运动步数效果
- Kotlin类型安全构建器的一次运用记录
- 两个surfaceView实现切换效果
- AndroidStudio4.0 New Class的坑(小结)
- Android日历控件的实现方法
- GetDiskFreeSpaceEx函数的一点处理
- Flutter轮播图效果的实现步骤
- Android自定义View实现五子棋游戏
- android简单自定义View实现五子棋
- 文件操作API
- Kotlin 扩展函数和扩展属性的使用方法
- PHP安全我见