我tmd复习了PAMSASAM多项式全家桶lct结果来了个裸到不能再裸的斯特林数定点打鸡
当场退役,明年再来
参考:https://www.cnblogs.com/ezoiLZH/p/9424911.html
其他性质:https://www.cnblogs.com/owenyu/p/6724661.html
常用式子
来自https://www.cnblogs.com/jz-597/p/13210825.html
第一类斯特林数
记作(left[egin{matrix}n\kend{matrix} ight])或(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)所以加上去也无所谓
快速计算
显然(s(n,k)=[x^k]prod_{i=0}^{n-1}(x+i))
设(F_n(x)=prod_{i=0}^{n-1}(x+i)=sum_{i=0}^{n-1}a_ix^i),那么(F_{2n}(x)=F_n(x)F_n(x+m))
于是有(F_n(x+m)=sum_{i=0}^{n-1}a_i(x+m)^i)
把后面的拆开变成卷积即可快速算,由于是倍增所以是(O(nlogn))的
例题
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
",1.0*sum/jc[n]);
}
fclose(stdin);
fclose(stdout);
return 0;
}
第二类斯特林数
记作(left{egin{matrix}n\kend{matrix} ight})或(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)^kinom{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)inom{x}{k}k!)
(=sum_{k=1}^n S(n,k)x^{underline{k}})
归纳证明:
(x^n=xsum_{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_isum_{k=0}^n k^ix^kinom{n}{k})
(huge =sum_{i=0}^m a_isum_{k=0}^n sum_{j=1}^i S(i,j)k^{underline{j}} x^kinom{n}{k})
(huge =sum_{i=0}^m a_isum_{j=1}^i S(i,j) n^{underline{j}}x^jsum_{k=j}^n x^{k-j}inom{n-j}{k-j})
(huge =sum_{i=0}^m a_isum_{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
",ans);
fclose(stdin);
fclose(stdout);
return 0;
}