第二类斯特林数小结

前言

csdn又更新了,然后版面还不好看

第二类斯特林数

根据我个人的经验,我觉得第一类斯特林数暂时没什么用
上面这句fake的话是不行的
所以这里只讨论第二类斯特林数
先是一般的递推式
S ( n , k ) = S ( n − 1 , k − 1 ) + S ( n − 1 , k ) ∗ k S(n,k)=S(n-1,k-1)+S(n-1,k)*k S(n,k)=S(n1,k1)+S(n1,k)k
然后也有单个求的
S ( n , k ) = 1 k ! ∑ i = 0 k ( − 1 ) i ∗ C k i ∗ ( m − k ) n S(n,k)=\frac{1}{k!}\sum_{i=0}^k{(-1)^i*C_k^i*(m-k)^n} S(n,k)=k!1i=0k(1)iCki(mk)n
然后一个比较常用的套路
因为我不会打下降幂,所以写成 f ( x ) f(x) f(x)
x n = ∑ k = 0 n S ( n , k ) ∗ x f ( k ) x^n=\sum_{k=0}^n{S(n,k)*x^{f(k)}} xn=k=0nS(n,k)xf(k)
然后还有一个技巧
就是
C ( x , k ) = x f ( k ) k ! C(x,k)=\frac{x^{f(k)}}{k!} C(x,k)=k!xf(k)
因此也可以写成
x n = ∑ k = 0 n S ( n , k ) ∗ k ! ∗ C ( x , k ) x^n=\sum_{k=0}^nS(n,k)*k!*C(x,k) xn=k=0nS(n,k)k!C(x,k)

一个题目

2159: Crash 的文明世界
就是用上面的式子展开一下就可以了。。
都是套路而已
我的题解
但应该也是可以自己推出来的吧。。
CODE:

#include<cstdio>
#include<cstring>
const int N=50005*2;
const int K=155;
const int MOD=10007;
int n,k;
struct qq
{
	int x,y,last;
}e[N];int num,last[N];
void init (int x,int y)
{
	num++;
	e[num].x=x;e[num].y=y;
	e[num].last=last[x];
	last[x]=num;
}
int JC[N];
int s[K][K];
int f[N][K];
void DP (int x,int fa)
{
	f[x][0]=1;
	for (int u=last[x];u!=-1;u=e[u].last)
	{
		int y=e[u].y;
		if (y==fa) continue;
		DP(y,x);
		f[x][0]=(f[x][0]+f[y][0])%MOD;
		for (int i=1;i<=k;i++)
			f[x][i]=(f[x][i]+(f[y][i]+f[y][i-1])%MOD)%MOD;
	}
}
int ans[N];
int calc (int x,int y){return ((x-y)%MOD+MOD)%MOD;}
int g[K];
void dfs (int x,int fa)
{
	for (int u=last[x];u!=-1;u=e[u].last)
	{
		int y=e[u].y;
		if (y==fa) continue;
		g[0]=calc(f[x][0],f[y][0]);
		for (int i=1;i<=k;i++)
			g[i]=calc(f[x][i],f[y][i]+f[y][i-1]);
		f[y][0]=f[y][0]+g[0];
		for (int i=1;i<=k;i++)
			f[y][i]=(f[y][i]+g[i]+g[i-1])%MOD;
		for (int i=1;i<=k;i++)	ans[y]=(ans[y]+s[k][i]*JC[i]%MOD*f[y][i]%MOD)%MOD;
		dfs(y,x);
	}
}
int main()
{
	num=0;memset(last,-1,sizeof(last));
    int tL, tNOW, tA, tB, tC;
    scanf("%d%d",&n,&k);
    scanf("%d%d%d%d%d",&tL,&tNOW,&tA,&tB,&tC);
    for (int u=1;u<n;u++)
    {
        int x,y;
        //scanf("%d%d",&x,&y);
        tNOW=(tNOW*tA+tB)%tC;
        x=u-tNOW%(u<tL?u:tL),y=u+1;
        init(x,y);init(y,x);
    }
  	JC[0]=1;for (int u=1;u<=k;u++) JC[u]=JC[u-1]*u%MOD;
  	s[0][0]=1;
	for (int u=1;u<=k;u++)
		for (int i=1;i<=k;i++)
			s[u][i]=(s[u-1][i-1]+s[u-1][i]*i%MOD)%MOD;
	DP(1,0);
	for (int u=1;u<=k;u++)	ans[1]=(ans[1]+s[k][u]*JC[u]%MOD*f[1][u]%MOD)%MOD;
	dfs(1,0);
	for (int u=1;u<=n;u++) printf("%d\n",ans[u]);
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值