斯特林数

斯特林数分为第一类斯特林数和第二类斯特林数,第一类斯特林数分为有符号斯特林数和无符号斯特林数;
这里写图片描述

1.什么是圆排列?
圆排列是把n个数中拿出k个数组成一个圆的种类数,则这里组成m个圆排列的意思是组成m个不同的圆的种类数;
2.第一类斯特林数:
斯特林数:
第一类斯特林数表示的是将n个不同元素分成k个不同的环的方案数。两个环不相同当且仅当这两个环不能通过旋转得到。
2.1有符号斯特林数公式:
考虑递推,把n个不同元素分成k个不同的环有两种转移。第一种,有可能是n−1个不同元素分成k−1个不同的环,当前的第n个独立成一个元素。第二种可能是n−1个不同元素已经分好了k个不同的环,当前这个可以加进去。加在每个已有元素的逆时针方向(或顺时针方向,方向没有关系,只要统一即可)就不会出现重复,共有n−1种方法。
第一类斯特林数的递推式:
s(n,k)=s(n−1,k−1)+s(n−1,k)∗(n−1);

2.2有符号斯特林数性质
1.s(0,0)=1s(0,0)=1
2.s(n,0)=0 n>0s(n,0)=0 n>0
3.s(n,1)=(n−1)!s(n,1)=(n−1)!
4.s(n,n−1)=C2ns(n,n−1)=Cn2
5.s(n,2)=(n−1)!∗∑n−1i=11is(n,2)=(n−1)!∗∑i=1n−11i
6.s(n,n−2)=2C3n+3C4ns(n,n−2)=2Cn3+3Cn4
7.∑nk=0s(n,k)=n!
8.s(n,n)=1;
2.3有符号和无符号的关系:
这里写图片描述

3.第二类斯特林数:
第二类斯特林数表示把n个元素分成k个非空集合的方案数,集合内是无序的。这样,我们很容易得出转移:分为两种情况。第一种情况,如果前n−1个元素组成了k−1个非空集合,那么当前元素自成一个集合。第二种情况,如果前n−1个元素组成了k个集合,那么当前的这个元素可以放进这k个集合中任意的一个。所以递推方程:
S(n,k)=S(n−1,k−1)+S(n−1,k)∗k

3.1 性质
1.S(0,0)=1S(0,0)=1
2.S(n,0)=0,n>0S(n,0)=0,n>0
3.S(n,n)=1S(n,n)=1
4.S(n,2)=S(n−1,1)+S(n−1,2)∗2=1+S(n−1,2)∗2=2n−1+1S(n,2)=S(n−1,1)+S(n−1,2)∗2=1+S(n−1,2)∗2=2n−1+1
5.S(n,n−1)=C2nS(n,n−1)=Cn2
6.S(n,n−2)=C3n+3C4nS(n,n−2)=Cn3+3Cn4 简单巧妙的证明:我们分成两种情况,把nn个不同的元素分成n−2n−2个集合有两种情况,分别是有一个集合有三个元素和有两个集合有两个元素。对于前者,我们选出三个元素为一个集合,其他的各成一个集合,这种情况的方案数就是C3nCn3。对于后者,先选出四个元素来,考虑怎么分配。当其中一个元素选定另一个元素形成同一个集合时,这种情况就确定了,所以是3C4n3Cn4。加法原理计算和即得证。
7.S(n,3)=12(3n−1+1)−2n−1S(n,3)=12(3n−1+1)−2n−1 数学归纳法
8.S(n,n−3)=C4n+10C5n+15C6nS(n,n−3)=Cn4+10Cn5+15Cn6 同性质六
9.通项公式:S(n,m)=1m!∑k=0m(−1)kCkm(m−k)n

参考:https://www.cnblogs.com/owenyu/p/6724661.html

未学会知识:利用斯特林公式求组合数;
4.斯特林公式
斯特林公式(Stirling’s approximation)是一条用来取n的阶乘的近似值的数学公式;
这里写图片描述

应用:求n!的位数
两种方法:
ans= lg(n!) = lg 1 + lg2 + ……+ lg n.
这里写图片描述

代码:

#include<stdio.h>
#include<math.h>
double reback(int n)
{
    double cnt=0;
    for(int i=2;i<=n;i++)
    {
        cnt+=log10(i);
    }
    return cnt;
}
int main()
{
    int cas,n;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d",&n);
        printf("%d\n",(int)reback(n)+1);
    }
    return 0;
}
#include <stdio.h>
#include <math.h>

const double PI = acos(-1.0);
const double ln_10 = log(10.0);

double reback(int N)
{
    return ceil((N*log(double(N))-N+0.5*log(2.0*N*PI))/ln_10);
}    

int main()
{
    int cas,n;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d",&n);
        if(n<=1)printf("1\n");
        else printf("%.0lf\n",reback(n));
    }
    return 0;
}
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值