zoukankan      html  css  js  c++  java
  • 斯特林数的四种求法

    斯特林数的四种求法

    一、第一类斯特林数求行

    因为

    [x^{overline{n}}=sum_{i=0}^{n}left[egin{matrix}n\iend{matrix} ight]x^i ]

    所以只要求出(x^{overline{n}})的系数就能求出第一类斯特林数的一行,那么如何求解(x^{overline{n}})呢?

    注意到(x^{overline{2n}}=x^{overline{n}}(x+n)^{overline{n}}),因此只要我们能够在已知(f(x))的情况下快速求解(f(x+n)),那么就可以通过(mathcal O(nlog(n)))完成。

    不妨设

    [f(x)=sum_{i=0}^{n}a_ix^i ]

    那么

    [egin{aligned} f(x+c)&=sum_{i=0}^{n}a_i(x+c)^i\ &=sum_{i=0}^{n}a_isum_{j=0}^{i}inom ijx^jc^{i-j}\ &=sum_{j=0}^{n}x^jsum_{i=j}^{n}a_iinom ij c^{i-j}\ &=sum_{j=0}^{n}dfrac{x^j}{j!}sum_{i=j}^{n}a_ii!dfrac{c^{i-j}}{(i-j)!} end{aligned} ]

    后面是一个减法卷积的形式了,于是可以(mathcal O(nlog(n)))快速求解。

    #include "poly.cpp"
    
    inline poly trans(poly f,int n,int c){
    	init_inv(n);
    	poly g;int t=1;
    	for(int i=0;i<n;t=1ll*t*c%mod,++i) f[i]=1ll*base[i]*f[i]%mod,g[i]=1ll*t*jc[i]%mod;
    	reverse(f.v.begin(),f.v.begin()+n);
    	poly h=Basic::mul(f,g,n,n),ret;
    	for(int i=0;i<n;++i) ret[i]=1ll*h[n-1-i]*jc[i]%mod;
    	return ret;
    }
    inline poly solve(int l,int r){
    	if(l>r) return poly(1);
    	if(l==r){poly g;g[1]=1;g[0]=l;return g;}
    	int len=r-l+1,mid=(l+r)>>1;
    	if(len&1) return Basic::mul(solve(l,mid),solve(mid+1,r),mid-l+2,r-mid+1);
    	else{
    		poly g=solve(l,mid),h=trans(g,mid-l+2,len/2);
    		return Basic::mul(g,h,mid-l+2,r-mid+1);
    	}
    }
    int main(){
    //	freopen("poly.in","r",stdin);
    	int n=Rint;
    	init_poly((n+1)<<1);
    	solve(0,n-1).print(n+1);
    	IO::flush();
    	return 0;
    }
    

    二、第二类斯特林数求行

    利用通项公式直接求解即可。

    [left{egin{matrix}n\mend{matrix} ight}=dfrac{1}{m!}sum_{k=0}^{m}(-1)^kinom{m}{k}(m-k)^n ]

    #include "poly.cpp"
    
    int n,m;
    poly f,g;
    int main(){
    //	freopen("poly.in","r",stdin);
    	n=Rint;
    	init_poly((n+1)<<1);
    	init_inv(n+1);
    	for(int i=0;i<=n;++i){
    		f[i]=1ll*jc[i]*(i&1?mod-1:1)%mod;
    		g[i]=1ll*ksm(i,n)*jc[i]%mod;
    	}
    	f=Basic::mul(f,g,n+1,n+1);f.print(n+1);
    	IO::flush();
    	return 0;
    } 
    

    三、第一类斯特林数求列

    一个环的EGF为

    [F(x)=sum_{i=1} dfrac{(i-1)!}{i!}x^i=ln(frac{1}{1-x}) ]

    于是答案的EGF就是:

    [frac{F(x)^k}{k!} ]

    (x!)是因为集合是无序的,而(k)次方把它当成了有序。

    #include "poly.cpp"
    
    int n,k,base[N],ivk;
    poly f;
    int main(){
    	scanf("%d%d",&n,&k);
    	if(n<k){for(int i=0;i<=n;++i) pc('0'),pc(' ');IO::flush();return 0;}
    	init_inv(n+1);
    	init_poly(n+1);
    	base[0]=1;
    	for(int i=1;i<=n;++i) base[i]=1ll*base[i-1]*i%mod;
    	int ivk=ksm(base[k],mod-2);
    	for(int i=1;i<=n;++i) f[i-1]=iv[i];
    	f=Exp::getpow(f,n,k);
    	for(int i=0;i<k;++i) pc('0'),pc(' ');
    	for(int i=k,j=0;i<=n;++i,++j)
    		put(1ll*f[j]*base[i]%mod*ivk%mod,' ');
    	IO::flush(); 
    	return 0;
    }
    

    四、第二类斯特林数求列

    一个集合的EGF为:

    [sum_{i=1}frac{1}{i!}x^i=e^x-1 ]

    于是同理多项式快速幂即可。

    #include "poly.cpp"
    
    int n,k,base[N],jc[N],ivk;
    poly f;
    int main(){
    	scanf("%d%d",&n,&k);
    	if(n<k){for(int i=0;i<=n;++i) pc('0'),pc(' ');IO::flush();return 0;}
    	init_inv(n+1);
    	init_poly(n+1);
    	base[0]=1;jc[0]=1;
    	for(int i=1;i<=n;++i) base[i]=1ll*base[i-1]*i%mod,jc[i]=1ll*jc[i-1]*iv[i]%mod;
    	int ivk=ksm(base[k],mod-2);
    	for(int i=1;i<=n;++i) f[i-1]=jc[i];
    	f=Exp::getpow(f,n-k+1,k);
    	for(int i=0;i<k;++i) pc('0'),pc(' ');
    	for(int i=k,j=0;i<=n;++i,++j)
    		put(1ll*f[j]*base[i]%mod*ivk%mod,' ');
    	IO::flush(); 
    	return 0;
    }
    
  • 相关阅读:
    github免费私有仓库使用
    空间域平滑滤波器
    Matlab常用函数
    图像处理之图像的平滑与锐化
    Matlab实现直方图均衡化
    matlab图像灰度调整——imadjust函数的使用
    调整图像大小调整图片大小
    Matlab 图像平移、旋转、缩放、镜像
    Matlab注释的几个方法
    训练一个神经网络 能让她认得我
  • 原文地址:https://www.cnblogs.com/tqxboomzero/p/14593272.html
Copyright © 2011-2022 走看看