第一类斯特林数
第一类Stirling数表示将 n 个不同元素构成m个圆排列的数目。
s
(
n
,
m
)
=
s
(
n
−
1
,
m
−
1
)
+
s
(
n
−
1
,
m
)
∗
(
n
−
1
)
s(n,m)=s(n-1,m-1)+s(n-1,m)*(n-1)
s(n,m)=s(n−1,m−1)+s(n−1,m)∗(n−1)
递推式
int stir1(int n,int m){
if(dp[n][m]!=-1) return dp[n][m];
else return dp[n][m]=stir1(n-1,m-1)+stir1(n-1,m)*(n-1);
}
int stir1(int n,int m){
if(dp[n][m]!=-1) return dp[n][m];
else return dp[n][m]=stir1(n-1,m-1)+stir1(n-1,m)*(n-1);
}
void pr(){
for(int i=1;i<=n;i++){
for(int j=0;j<=i;j++){
printf("%d ",dp[i][j]);
}printf("\n");
}
}
int main(){
scanf("%d%d",&n,&m);
memset(dp,-1,sizeof dp);
for(int i=1;i<=n;i++) dp[i][0]=0;
for(int i=1;i<=n;i++) dp[i][i]=1;
printf("%d\n",stir1(n,m));
pr();
}
矩阵式
int stir1(int n,int m){
dp[1][1]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<=i;j++){
dp[i][j]=dp[i-1][j-1]+dp[i-1][j]*(i-1);
}
}
return dp[n][m];
}
void pr(){
for(int i=1;i<=n;i++){
for(int j=0;j<=i;j++){
printf("%d ",dp[i][j]);
}printf("\n");
}
}
int main(){
scanf("%d%d",&n,&m);
printf("%d\n",stir1(n,m));
pr();
}
第二类斯特林数
第二类Stirling数实际上是集合的一个拆分,表示将n个不同的元素拆分成m个集合的方案数。
s
(
n
,
m
)
=
s
(
n
−
1
,
m
−
1
)
+
s
(
n
−
1
,
m
−
1
)
∗
m
s(n,m)=s(n-1,m-1)+s(n-1,m-1)*m
s(n,m)=s(n−1,m−1)+s(n−1,m−1)∗m
递推式
int stir2(int n,int m){
if(dp[n][m]!=-1) return dp[n][m];
else return dp[n][m]=stir2(n-1,m-1)+m*stir2(n-1,m);
}
int stir2(int n,int m){
if(dp[n][m]!=-1) return dp[n][m];
else return dp[n][m]=stir2(n-1,m-1)+m*stir2(n-1,m);
}
void pr(){
for(int i=1;i<=n;i++){
for(int j=0;j<=i;j++){
printf("%d ",dp[i][j]);
}printf("\n");
}
}
int main(){
scanf("%d%d",&n,&m);
memset(dp,-1,sizeof dp);
for(int i=1;i<=n;i++) dp[i][0]=0;
for(int i=1;i<=n;i++) dp[i][i]=1;
printf("%d\n",stir2(n,m));
pr();
}
矩阵式
int stir2(int n,int m){
dp[1][1]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<=i;j++){
dp[i][j]=dp[i-1][j-1]+j*dp[i-1][j];
}
}
return dp[n][m];
}
void pr(){
for(int i=1;i<=n;i++){
for(int j=0;j<=i;j++){
printf("%d ",dp[i][j]);
}printf("\n");
}
}
int main(){
scanf("%d%d",&n,&m);
printf("%d\n",stir2(n,m));
pr();
}
转化关系
两类Stirling数存在以下转置关系