第二类斯特林数$\left\{\begin{matrix}n\\m\end{matrix}\right\}$表示把含有$n$个不同的数的集合划分为$m$个非空子集的方案数
递推式$\left\{\begin{matrix}n\\m\end{matrix}\right\}=m\left\{\begin{matrix}n-1\\m\end{matrix}\right\}+\left\{\begin{matrix}n-1\\m-1\end{matrix}\right\}$,边界$\left\{\begin{matrix}n\\0\end{matrix}\right\}=[n=0]$,可以这样看:已经分好了$n-1$个数,第$n$个数可以单独分成一个子集,也可以分到之前的$m$个子集中(因为这些子集中有数,所以它们是不同的)
一个固定$n$的通项公式$\begin{align*}\left\{\begin{matrix}n\\m\end{matrix}\right\}=\dfrac1{m!}\sum\limits_{k=0}^m(-1)^k\binom mk(m-k)^n\end{align*}$,相当于从不管非空子集限制的方案($m^n$)中容斥掉有$k$个空子集的方案
它具有卷积的形式,可以用FFT在$O(m\log_2m)$的时间内算出$\left\{\begin{matrix}n\\1\end{matrix}\right\}\cdots\left\{\begin{matrix}n\\m\end{matrix}\right\}$
第一类斯特林数$\left[\begin{matrix}n\\m\end{matrix}\right]$表示把$n$个不同的数划分为$m$个非空轮换的方案数
递推式$\left[\begin{matrix}n\\m\end{matrix}\right]=(n-1)\left[\begin{matrix}n-1\\m\end{matrix}\right]+\left[\begin{matrix}n-1\\m-1\end{matrix}\right]$,边界$\left[\begin{matrix}n\\0\end{matrix}\right]=[n=0]$,可以这样看:已经分好了$n-1$个数,第$n$个数可以单独分成一个轮换,也可以分到之前的轮换中,我们把它插到每个轮换的每一个数后面都可以形成新的轮换,所以有$n-1$种方法
它的另一个定义是$\begin{align*}x^\underline n=\sum\limits_{k=0}^n(-1)^{n-k}\left[\begin{matrix}n\\k\end{matrix}\right]x^k\end{align*}$,用归纳法易证它满足上面的递推性质
$\begin{align*}x^\underline n&=(x-n+1)x^\underline{n-1}\\&=(x-n+1)\sum\limits_{k=0}^{n-1}(-1)^{n-1-k}\left[\begin{matrix}n-1\\k\end{matrix}\right]x^k\\&=\left(\sum\limits_{k=1}^n(-1)^{n-k}\left[\begin{matrix}n-1\\k-1\end{matrix}\right]x^k\right)+\left(\sum\limits_{k=0}^{n-1}(-1)^{n-k}(n-1)\left[\begin{matrix}n-1\\k\end{matrix}\right]x^k\right)\\&=\sum\limits_{k=0}^n(-1)^{n-k}\left((n-1)\left[\begin{matrix}n-1\\k\end{matrix}\right]+\left[\begin{matrix}n-1\\k-1\end{matrix}\right]\right)x^k\end{align*}$
好像没有通项,但是要求还是可以的,考虑计算$x^\underline n$的各项系数,我们采用分治的做法:由$x^\underline n$推$x^\underline{2n}$
如果已经计算好了$\begin{align*}x^\underline n=\sum\limits_{i=0}^n(-1)^{n-i}\left[\begin{matrix}n\\i\end{matrix}\right]x^i\end{align*}$,因为$x^\underline{2n}=x^\underline n(x-n)^\underline n$,所以我们还要计算$(x-n)^\underline n$
$\begin{align*}(x-n)^\underline n&=\sum\limits_{i=0}^n(-1)^{n-i}\left[\begin{matrix}n\\i\end{matrix}\right](x-n)^i\\&=\sum\limits_{i=0}^n(-1)^{n-i}\left[\begin{matrix}n\\i\end{matrix}\right]\sum\limits_{j=0}^i\binom ijx^j(-n)^{i-j}\end{align*}$
第二个sigma是卷积的形式,我们可以用FFT预处理,最后再用FFT把两个多项式乘起来,设时间复杂度为$T(n)$,则$T(n)=O(n\log_2n)+T\left(\dfrac n2\right)$,解得$T(n)=O(n\log_2n)$,也就是说我们可以在$O(n\log_2n)$的时间内算出$\left[\begin{matrix}n\\1\end{matrix}\right]\cdots\left[\begin{matrix}n\\n\end{matrix}\right]$
上面就是这两个东西本身的性质,应用嘛...并没有想到什么
算了先挂一个BZOJ4555充数吧==
题意:求$\begin{align*}\sum\limits_{i=0}^n\sum\limits_{j=0}^i\left\{\begin{matrix}i\\j\end{matrix}\right\}2^jj!\end{align*}$
$\begin{align*}\sum\limits_{i=0}^n\sum\limits_{j=0}^n\left\{\begin{matrix}i\\j\end{matrix}\right\}2^jj!&=\sum\limits_{i=0}^n\sum\limits_{j=0}^n2^j\sum\limits_{k=0}^j(-1)^{j-k}\binom jkk^i\\&=\sum\limits_{j=0}^n2^jj!\sum\limits_{k=0}^j\dfrac{(-1)^{j-k}}{(j-k)!}\dfrac1{k!}\sum\limits_{i=0}^nk^i\end{align*}$
第三个sigma是等比数列求和(注意当$k=0$时求和结果是$1$),第二个sigma有卷积的形式,可以用FFT预处理
庆祝一下==我终于真正会写FFT/NTT了...(菜,没办法)
#include<stdio.h>
const int mod=998244353;
typedef long long ll;
int mul(int a,int b){return a*(ll)b%mod;}
int ad(int a,int b){return(a+b)%mod;}
int de(int a,int b){return(a-b)%mod;}
int pow(int a,int b){
int s=1;
while(b){
if(b&1)s=mul(s,a);
a=mul(a,a);
b>>=1;
}
return s;
}
int rev[300010],N,iN;
void pre(int n){
int k,i;
for(N=1,k=0;N<=n;N<<=1)k++;
for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
iN=pow(N,mod-2);
}
void swap(int&a,int&b){a^=b^=a^=b;}
void ntt(int*a,int on){
int i,j,k,t,w,wn;
for(i=0;i<N;i++){
if(i<rev[i])swap(a[i],a[rev[i]]);
}
for(i=2;i<=N;i<<=1){
wn=pow(3,(on==1)?(mod-1)/i:(mod-1-(mod-1)/i));
for(j=0;j<N;j+=i){
w=1;
for(k=0;k<i>>1;k++){
t=mul(a[i/2+j+k],w);
a[i/2+j+k]=de(a[j+k],t);
a[j+k]=ad(a[j+k],t);
w=mul(w,wn);
}
}
}
if(on==-1){
for(i=0;i<N;i++)a[i]=mul(a[i],iN);
}
}
int a[300010],b[300010],fac[300010],rfac[300010],inv[300010];
int main(){
int n,i,s,bas;
scanf("%d",&n);
fac[0]=1;
for(i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
rfac[n]=pow(fac[n],mod-2);
for(i=n;i>0;i--)rfac[i-1]=mul(rfac[i],i);
for(i=1;i<=n;i++)inv[i]=mul(rfac[i],fac[i-1]);
for(i=0;i<=n;i++){
a[i]=((i&1)?-1:1)*rfac[i];
if(i==0)
b[i]=1;
else if(i==1)
b[i]=mul(n+1,rfac[i]);
else if(i>1)
b[i]=mul(mul(pow(i,n+1)-1,inv[i-1]),rfac[i]);
}
pre(n<<1);
ntt(a,1);
ntt(b,1);
for(i=0;i<N;i++)a[i]=mul(a[i],b[i]);
ntt(a,-1);
s=0;
bas=1;
for(i=0;i<=n;i++){
s=ad(s,mul(mul(bas,fac[i]),a[i]));
bas=mul(bas,2);
}
printf("%d",(s+mod)%mod);
}
第一类斯特林数我只遇到过一个:[xsy1515]小学生数学题,如果一道题中的自然数幂求和$n$很大,要求多个,甚至模数不同,那么就可以转成斯特林数$O(k^2)$做
很空虚==毕竟做题太少没什么题放出来