组合数学学习笔记(四):特殊的数
卡塔兰数( )
斯特林数( )
斯特林数作为组合数学中非常重要的一类数,一共分为第一类斯特林数与第二类斯特林数,在处理复杂的小球与盒子的关系时有重要的作用。我们先从比较简单的第二类斯特林数讲起。
第二类斯特林数
定义
记
第二类斯特林数有一些特殊值:
-
:将非零个元素划分为 个集合不存在,将 个元素划分为 个集合算一种情况; -
,将 个元素划分为 个集合,每个元素只能放入这一个集合中;将 个元素划分为 个集合,每个元素只能单独成一个集合; -
,考虑先将 划分到一个集合,再考虑其它 个数是放在有 的这个集合,还是没 的这个集合,最后减去全放在有 的这个集合中的 种情况; -
,考虑到此时只有 个集合大小为 ,枚举一下是哪个集合即可。
递推公式与通项公式
递推公式
即考虑第
通项公式
证明:设将
对于
二项式反演一下,可以得到
由于
生成函数
应用
高阶差分
普通幂转下降幂
可以发现它的系数正好是第二类斯特林数,因此可以得出结论:
证明:
考虑数学归纳法,当
首先,我们知道
那么
考虑到
即,我们可以将第二类斯特林数看成,由普通幂转为下降幂时,产生的系数。
普通幂转上升幂
类似下降幂来定义上升幂为
我们将
第一类斯特林数
定义
记
圆排列是指将一个排列围成一个圈,如果两个圆排列旋转之后一样,那么这两个圆排列就是相同的,比如
第一类斯特林数有一些特殊值:
-
:将非零个元素划分为 个圆排列不存在,将 个元素划分为 个圆排列算一种情况; -
:将 个元素划分为 个圆排列,每个元素只能单独成一个圆排列; -
:考虑到普通排列的数量有 个,每个圆排列对应 个普通排列,于是圆排列的数量就变成了 ; -
,考虑到此时只有 个圆排列大小为 ,枚举一下是哪个圆排列即可。
可以发现,在第二类斯特林数分成的
递推公式
即考虑第
由于第
可惜的是,第一类斯特林数没有实用的通项公式 (虽然第二类斯特林数的通项公式也不实用)。
生成函数
应用
上升幂转普通幂
可以发现它的系数正好是第一类斯特林数,因此可以得出结论:
证明:
还是考虑数学归纳法,当
这次,我们要知道
那么
一样的道理,
即,我们可以将第一类斯特林数看成,从上升幂转普通幂时,产生的常数。
下降幂转普通幂
考虑到上升幂和下降幂奇数次方项的系数正好相反:
因为
解:首先把
由于
可以发现里面是一个二项式定理的形式,于是原式最终
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e3 + 9;
int s[N][N], d[N], a[N], b[N], n, x, p, m;
int qpow(int a, int b){
int res = 1;
while(b > 0){
if(b & 1)
res = res * a % p;
a = a * a % p;
b >>= 1;
}
return res;
}
signed main(){
scanf("%lld%lld%lld%lld", &n, &x, &p, &m);
s[0][0] = 1;
for(int i = 1; i < N; i++)
for(int j = 1; j < N; j++)
s[i][j] = (j * s[i - 1][j] + s[i - 1][j - 1]) % p;
for(int i = 0; i <= m; i++)
scanf("%lld", &a[i]);
for(int i = 0; i <= m; i++)
for(int j = i; j <= m; j++)
b[i] = (b[i] + s[j][i] * a[j]) % p;
d[0] = 1;
for(int i = n, j = 1; i >= (n - m + 1); i--, j++)
d[j] = d[j - 1] * i % p;
int ans = 0;
for(int i = 0; i <= m; i++)
ans = (ans + b[i] * d[i] % p * qpow(x, i) % p * qpow(x + 1, n - i) % p) % p;
printf("%lld", ans);
return 0;
}
这个建筑师建造的城市让我想起了 指环王 中的:
考虑把最大值作为分界点,左边的前缀最大值构成一个
现在每个阶梯分成一个组,每个组内除了最大值必须在第一个,其它值可以随便排,考虑到高度是
现在考虑哪些值在左边的阶梯,哪些值在右边的阶梯,因此分左右的组合有
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e4 + 9, M = 2e2 + 9, MOD = 1e9 + 7;
int s[N][M], b[M][M], T, n, A, B;
signed main(){
s[0][0] = 1;
for(int i = 1; i < N; i++)
for(int j = 1; j < M; j++)
s[i][j] = ((i - 1) * s[i - 1][j] + s[i - 1][j - 1]) % MOD;
for(int i = 0; i < M; i++)
b[i][0] = 1;
for(int i = 1; i < M; i++)
for(int j = 1; j < M; j++)
b[i][j] = (b[i - 1][j] + b[i - 1][j - 1]) % MOD;
scanf("%lld", &T);
while(T--){
scanf("%lld%lld%lld", &n, &A, &B);
printf("%lld\n", s[n - 1][A + B - 2] * b[A + B - 2][A - 1] % MOD);
}
return 0;
}
例题五
给定
-
; -
。
斯特林数恒等式
斯特林数与伯努利数的关系
我们现在学过的特殊的数有:组合数、卡塔兰数、伯努利数、斯特林数,其中伯努利数与斯特林数有一些密切的关系。
第二类斯特林数求行
第二类斯特林数求列
第一类斯特林数求行
第一类斯特林数求列
斯特林反演
欧拉数( )
调和级数( )
伯努利数( )
考虑自然数的幂的和
可以发现系数之间存在一些关系。首先可以发现
伯努利数隐含一个递归关系:
伯努利数意义的证:考虑数学归纳法。
边界情况是好证的,同时我们也可以证明
假设对于
首先,先进行一个简单的变换,那就是
现在考虑一个新的求和方法:扰动法。我们先设
由于
将
考虑改变
发现其中有一个三项式系数恒等,将其变换后再调整求和顺序可以得到原式
再次改变
可以发现
现在我们就知道了
分拆数( )
施罗德数( )
本文来自博客园,作者:JPGOJCZX,转载请注明原文链接:https://www.cnblogs.com/JPGOJCZX/p/18688631
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效