一二类斯特林数小结

我tmd复习了PAMSASAM多项式全家桶lct结果来了个裸到不能再裸的斯特林数定点打鸡

当场退役,明年再来

参考:https://www.cnblogs.com/ezoiLZH/p/9424911.html

其他性质:https://www.cnblogs.com/owenyu/p/6724661.html

第一类斯特林数

记作\(\left[\begin{matrix}n\\k\end{matrix}\right]\)\(s(n,k)\),表示把n个数分成k个环,环相同数不同且有序的方案数

\(s(n,k)=s(n-1,k-1)+s(n-1,k)(n-1)\)

n自成一个环,或者插到前n-1个数之后

性质1

\(s(n,1)=(n-1)!\)

证明1

就是一个环的方案,被算了n次就除n

性质2

\(s(n,2)=(n-1)!\sum_{i-1}^{n-1}\frac{1}{i}\)

证明2

简单归纳

\(s(n,2)=s(n-1,1)+s(n-1,2)(n-1)\)

\(=s(n-1,1)+(n-1)(n-2)!\sum_{i-1}^{n-2}\frac{1}{i}\)

\(=(n-2)!+(n-1)!\sum_{i-1}^{n-2}\frac{1}{i}\)

\(=(n-1)!\sum_{i-1}^{n-1}\frac{1}{i}\)

性质3

\(\sum_{i=0}^n s(n,k)=n!\)

证明3

把i向枚举的排列pi连边,发现构成了若干环,枚举环个数k即可

\(s(n,0)=0\)所以加上去也无所谓

例题

hdu3625

额外的限制就是第一个人独自成环,减去s(n-1,1~k-1)

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;

ll S[21][21],jc[21],sum;
int T,n,m,i,j,k,l;

int main()
{
	#ifdef file
	freopen("hdu3625.in","r",stdin);
	#endif
	
	S[0][0]=jc[0]=1;
	fo(i,1,20) {jc[i]=jc[i-1]*i; fo(j,1,i) S[i][j]=S[i-1][j-1]+S[i-1][j]*(i-1);}
	
	scanf("%d",&T);
	for (;T;--T)
	{
		scanf("%d%d",&n,&m);sum=0;
		fo(i,1,m) sum+=S[n][i]-S[n-1][i-1];
		printf("%.4lf\n",1.0*sum/jc[n]);
	}
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}

第二类斯特林数

记作\(\left\{\begin{matrix}n\\k\end{matrix}\right\}\)\(S(n,k)\),表示把n个数分成k组,组相同数不同且无序的方案数

\(S(n,k)=S(n-1,k-1)+S(n-1,k)k\)

n自成一个组,或者插到k个组里

通项公式

\(S(n,k)=\frac{1}{k!}\sum_{i=0}^m (-1)^k\binom{k}{i}(m-k)^n\)

枚举空集合容斥,最后除m!变无序

可以卷积优化

转化幂

重中之重

\(x^n=\sum_{k=1}^n S(n,k)x^{\underline{k}}\),下降幂可以为0

直接证明:

等价于n个不同的球放到x个不同的盒子里,盒子可以为空的方案,枚举有多少个盒子有球,斯特林数乘上阶乘变成盒子不同

\(x^n=\sum_{k=1}^n S(n,k)\binom{x}{k}k!\)

\(=\sum_{k=1}^n S(n,k)x^{\underline{k}}\)

归纳证明:

\(x^n=x\sum_{k=1}^{n-1} S(n-1,k)x^{\underline{k}}\)

\(=((x-k)+k)\sum_{k=1}^{n-1} S(n-1,k)x^{\underline{k}}\)

\(=\sum_{k=1}^{n-1} S(n-1,k)(x^{\underline{k+1}}+kx^{\underline{k}})\)

\(=\sum_{k=2}^{n} S(n-1,k-1)x^{\underline{k}}+\sum_{k=1}^{n-1}S(n-1,k)kx^{\underline{k}}\)

前面的k=1时为0,后面的k=n时为0,所以扩展一下

\(=\sum_{k=1}^{n} S(n-1,k-1)x^{\underline{k}}+S(n-1,k)kx^{\underline{k}}\)

\(=\sum_{k=1}^{n} S(n,k)x^{\underline{k}}\)

例题

loj#3300. 「联合省选 2020 A」组合数问题

垃圾裸题

\(\huge ans=\sum_{i=0}^m a_i\sum_{k=0}^n k^ix^k\binom{n}{k}\)

\(\huge =\sum_{i=0}^m a_i\sum_{k=0}^n \sum_{j=1}^i S(i,j)k^{\underline{j}} x^k\binom{n}{k}\)

\(\huge =\sum_{i=0}^m a_i\sum_{j=1}^i S(i,j) n^{\underline{j}}x^j\sum_{k=j}^n x^{k-j}\binom{n-j}{k-j}\)

\(\huge =\sum_{i=0}^m a_i\sum_{j=1}^i S(i,j) n^{\underline{j}}x^j(x+1)^{n-j}\)

//nmsl
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
#define file
using namespace std;

ll S[1001][1001],C[1001][1001],a[1001],ans,Ans,X,s;
int i,j,k,l,n,x,mod,m;

ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}

int main()
{
	#ifdef file
	freopen("loj3300.in","r",stdin);
	#endif
	
	scanf("%d%d%d%d",&n,&x,&mod,&m);S[0][0]=1;
	fo(i,1,m) fo(j,1,i) S[i][j]=(S[i-1][j-1]+S[i-1][j]*j)%mod;
	fo(i,0,m) {C[i][0]=C[i][i]=1; fo(j,1,i-1) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;}
	fo(i,0,m) scanf("%lld",&a[i]);
	
	ans=a[0]*qpower(x+1,n)%mod;
	fo(i,1,m)
	{
		Ans=0;X=1;
		s=1;
		fo(j,1,i)
		{
			s=s*(n-j+1)%mod*x%mod;
			Ans=(Ans+s*S[i][j]%mod*qpower(x+1,n-j))%mod;
		}
		ans=(ans+Ans*a[i])%mod;
	}
	printf("%lld\n",ans);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/gmh77/p/13170198.html