第二类斯特林数$\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)$做
很空虚==毕竟做题太少没什么题放出来