• 第一类斯特林数求行


    solution

    首先我们有

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

    因此只用求出(x^{overline n}) 的各项系数就可以算出一行的第一类斯特林数了

    如何快速计算?考虑倍增。假设已经计算出(x^{overline n}) ,要求(x^{overline{2n}}) ,首先我们有

    [x^{overline {2n}}=x^{overline n}cdot (x+n)^{overline n} ]

    由此问题转化为已知(f(x)) ,如何求出(f(x+n)) 。推导如下(以下记(f_i=[x^i]f(x)))

    [f(x+n)=sum_{i=0}^ka_i(x+n)^i\ =sum_{i=0}^ka_isum_{j=0}^iinom ijx^jn^{i-j}\ =sum_{j=0}^kx^jsum_{i=j}^ka_iinom ijn^{i-j}\ =sum_{j=0}^kx^jsum_{i=0}^{k-j}a_{i+j}inom {i+j}jn^{i}\ =sum_{j=0}^kfrac 1{j!}x^jsum_{i=0}^{k-j}a_{i+j} {(i+j)!}frac {n^{i}}{i!}\ ]

    [B_i=a_ii!\ A_i=frac {n^i}{i!} ]

    [=sum_{j=0}^kfrac 1{j!}x^jsum_{i=0}^{k-j}B_{i+j}A_{i}\ =sum_{j=0}^kfrac 1{j!}x^jsum_{i=0}^{k-j}Br_{k-i-j}A_{i}\ ]

    其中(Br) 满足(Br_{i}=B_{k-i}) .令(C=Br*A) ,则

    [=sum_{j=0}^kfrac 1{j!}x^jC_{k-j}\ =sum_{j=0}^kfrac {C_{k-j}}{j!}x^j\ ]

    这样就可以求出(f(x+n)) 的各项系数,然后再和(f(x)) 卷积即可

    time complexity

    [T(n)=T(frac n2)+mathcal O(nlog_2n) ]

    根据(master) 定理得(T(n)=mathcal O(nlog_2n))

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=262150,G=3,ivG=55924054,mod=167772161;
    struct poly
    {
    	vector<int>v;
    	inline int&operator[](int x)
    	{
    		while(v.size()<=x)v.push_back(0);
    		return v[x];
    	}
    	inline void pre(int p,int lim)
    	{
    		int t=min((int)v.size(),lim);
    		for(int i=p;i<t;++i)v[i]=0;
    	}
    };
    namespace Math
    {
    	int inv[N],fac[N],fiv[N];
    	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    	inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
    	inline int qpow(int x,int y)
    	{
    		int ans=1;
    		for(;y;y>>=1,x=1ll*x*x%mod)
    			if(y&1)ans=1ll*ans*x%mod;
    		return ans;
    	}
    	inline void init(int n)
    	{
    		inv[1]=1;for(int i=2;i<=n;++i)inv[i]=mod-1ll*mod/i*inv[mod%i]%mod;
    		fac[0]=1;for(int i=1;i<=n;++i)fac[i]=1ll*fac[i-1]*i%mod;
    		fiv[n]=qpow(fac[n],mod-2);for(int i=n-1;~i;--i)fiv[i]=1ll*fiv[i+1]*(i+1)%mod;
    	}
    }
    using namespace Math;
    namespace Basis
    {
    	int rev[N<<2],fr[N<<2],wn[N<<2];
    	inline void pre(int lim,int l)
    	{
    		for(int i=0;i<lim;++i)
    			rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    	}
    	inline void NTT(int lim,poly&f,bool tp)
    	{
    		for(int i=0;i<lim;++i)fr[i]=f[rev[i]];
    		for(int mid=1;mid<lim;mid<<=1)
    		{
    			int len=mid<<1,t=qpow(tp?ivG:G,(mod-1)/len);
    			wn[0]=1;for(int i=1;i<mid;++i)wn[i]=1ll*wn[i-1]*t%mod;
    			for(int j=0;j+len-1<lim;j+=len)
    				for(int k=0;k<mid;++k)
    				{
    					int x=fr[j+k],y=1ll*wn[k]*fr[j+mid+k]%mod;
    					fr[j+k]=add(x,y),fr[j+mid+k]=dec(x,y);
    				}
    		}
    		for(int i=0;i<lim;++i)f[i]=fr[i];
    	}
    	inline poly mul(int n,poly f,int m,poly g)
    	{
    		int lim=1,l=0;while(lim<n+m)lim<<=1,++l;
    		pre(lim,l);f.pre(n,lim),g.pre(m,lim);
    		NTT(lim,f,0);NTT(lim,g,0);
    		for(int i=0;i<lim;++i)f[i]=1ll*f[i]*g[i]%mod;
    		NTT(lim,f,1);int iv=qpow(lim,mod-2);
    		for(int i=0;i<lim;++i)f[i]=1ll*f[i]*iv%mod;
    		return f;
    	}
    }
    poly solve(int n)
    {
    	if(n==1){poly f;f[0]=1;return f;}
    	if(n&1)
    	{
    		int m=n/2+1;
    		poly f=solve(m),A,Br,fm;
    		A[0]=1;for(int i=1;i<m;++i)A[i]=1ll*A[i-1]*(m-1)%mod*inv[i]%mod;
    		for(int i=0;i<m;++i)Br[m-1-i]=1ll*f[i]*fac[i]%mod;
    		poly C=Basis::mul(m,A,m,Br);
    		for(int i=0;i<m;++i)fm[i]=1ll*C[m-1-i]*fiv[i]%mod;
    		return Basis::mul(m,fm,m,f);
    	}
    	else
    	{
    		poly f=solve(n-1),g;
    		for(int i=1;i<n;++i)g[i]=add(f[i-1],1ll*(n-2)*f[i]%mod);
    		return g;
    	}
    }
    int main()
    {
    	int n;scanf("%d",&n);init(n);
    	poly f=solve(n+1);
    	for(int i=0;i<=n;++i)printf("%d ",f[i]);
    	return 0;
    }
    
    NO PAIN NO GAIN
  • 相关阅读:
    缺失值的常见填充方法
    多变量线性回归
    回归(补充)
    单变量线性回归
    监督学习和非监督学习
    Java学习-数组(1)
    如何发布一个npm包(基于vue)
    《麦肯锡教给我的写作武器》摘录
    自定义博客样式
    ubuntu 下配置elasticSearch
  • 原文地址:https://www.cnblogs.com/zmyzmy/p/14402695.html
Copyright © 2020-2023  润新知