bzoj 2159: Crash 的文明世界

本文通过一个具体的图论题目介绍了斯特林数的应用。作者首先回顾了斯特林数的基本概念,并通过一道需要求解特定排列组合的问题来展示如何利用斯特林数进行计算。文章还分享了一个C++实现的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个博客已经更新:新的文章

前言

今天在复习初赛。。
复习排列组合。。
发现斯特林数没学过TAT
于是就去学了一发。。
教程我就不写了。。
于是就来做题了。。

题意

你就看题面那张图就可以了

题解

对于要输出n个数的题我都不是很会做。。
于是就%题解
真的牛逼。。我觉得他已经讲得很清楚了
至于那个用下降幂表示通常幂,具体数学那本书的斯特林数上面有证明。。
一开始我还不知道在证明什么东西,做了这题才知道
证明斯特林数就是他的系数。。
然后转换一下,就可以变成C了。。

差不多搬运了个代码:

#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 fac[K];//阶乘? 
int S[K][K];//斯特林数 
int f[N][K];
void DP (int x,int ff)
{
	f[x][0]=1;
	for (int u=last[x];u!=-1;u=e[u].last)
	{
		int y=e[u].y;
		if (y==ff) 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 g[K],h[K];
int jian (int x,int y)
{
	return ((x-y)%MOD+MOD)%MOD;
}
void calc (int x,int ff)
{
	for (int u=last[x];u!=-1;u=e[u].last)
	{
		int y=e[u].y;
		if (y==ff) continue;
		g[0]=f[x][0];
		g[0]=jian(g[0],f[y][0]);
		h[0]=n;
		for (int i=1;i<=k;i++)
		{
			g[i]=f[x][i];
			g[i]=jian(g[i],f[y][i]+f[y][i-1]);
			h[i]=(f[y][i]+g[i]+g[i-1])%MOD;
		}
		for (int i=0;i<=k;i++)
			f[y][i]=h[i];
		for (int i=1;i<=k;i++)
			ans[y]=(ans[y]+S[k][i]*fac[i]%MOD*h[i]%MOD)%MOD;
		calc(y,x);
	}
}
int main()
{
	 int tL, tNOW, tA, tB, tC;
	num=0;memset(last,-1,sizeof(last));
	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);
	}
	
	fac[0]=1;
	for (int u=1;u<=k;u++)
		fac[u]=(fac[u-1]*u)%MOD;
	
	S[0][0]=1;
	for (int u=1;u<=k;u++)
		for (int i=1;i<=u;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]*fac[u]%MOD*f[1][u]%MOD)%MOD;
		
	calc(1,0);
	for (int u=1;u<=n;u++) printf("%d\n",ans[u]);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值