• BZOJ 4555:[TJOI2016&HEOI2016]求和(第二类斯特林数+NTT)


    题目链接


    (Description)

    [sum_{i=0}^nsum_{j=0}^iS(i,j)2^jj!$$对998244353取模后的结果。 $n<=10^5$ --- $Solution$ $S(i,j)$在这里就非常碍事,怎么把它写成一个多项式的形式呢? 第二类斯特林数还有一种容斥的写法 $$S(n,m)=frac{1}{m!}sum_{i=0}^m(-1)^iC_m^i(m-i)^n]

    把它带到要求的式子里去

    [sum_{i=0}^nsum_{j=0}^i2^jj!frac{1}{j!}sum_{k=0}^j(-1)^kfrac{j!}{k!(j-k)!}(j-k)^i ]

    [=sum_{j=0}^n2^jj!sum_{k=0}^jfrac{(-1)^k}{k!}frac{sum_{i=0}^n(j-k)^i}{(j-k)!} ]

    最后是个等比数列求和

    [sum_{j=0}^n2^jj!sum_{k=0}^jfrac{(-1)^k}{k!}frac{(j-k)^{n+1}-1}{(j-k-1)(j-k)!} ]

    后边的求和直接(NTT)做。

    #include<complex>
    #include<cstdio>
    using namespace std;
    const int mod=998244353,R=3;
    const int N=3e5+7;
    int n,invR;
    int F[N],G[N],fac[N],finv[N],r[N];
    int qread()
    {
    	int x=0;
    	char ch=getchar();
    	while(ch<'0' || ch>'9')ch=getchar();
    	while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return x;
    }
    int Fpow(long long b,int p)
    {
    	long long res=1;
    	for(;p;p>>=1,b=b*b%mod)
    		if(p&1)res=res*b%mod;
    	return res;
    }
    void NTT(int *a,int lim,int opt)
    {
    	for(int i=1;i<lim;i++)
    		if(i<r[i])swap(a[i],a[r[i]]);
    	for(int i=2;i<=lim;i<<=1)
    	{
    		int mid=i>>1,Wn=Fpow(~opt?R:invR,(mod-1)/i),t;
    		for(int j=0;j<lim;j+=i)
    		{
    			long long w=1;
    			for(int k=j;k<j+mid;k++,w=w*Wn%mod)
    			{
    				t=1ll*w*a[k+mid]%mod;
    				a[k+mid]=(a[k]-t+mod)%mod;a[k]=(a[k]+t)%mod;
    			}
    		}
    	}
    	if(opt==-1)for(int i=0,inv=Fpow(lim,mod-2);i<lim;i++)a[i]=1ll*a[i]*inv%mod;
    }
    int main()
    {
    	scanf("%d",&n);
    	fac[0]=finv[0]=1;
    	for(int i=1;i<=n;i++)
    		fac[i]=1ll*fac[i-1]*i%mod;
    	finv[n]=Fpow(fac[n],mod-2);
    	for(int i=n-1;i;i--)
    		finv[i]=1ll*finv[i+1]*(i+1)%mod;
    	for(int i=2;i<=n;i++)
    		F[i]=1ll*(Fpow(i,n+1)-1)*Fpow(i-1,mod-2)%mod*finv[i]%mod;
    	F[0]=1;F[1]=n+1;
    	for(int i=0;i<=n;i++)
    		G[i]=((i&1?-1:1)*finv[i]+mod)%mod;
    	int lim=1,l=-1;
    	invR=Fpow(R,mod-2);
    	while(lim<=n+n)lim<<=1,l++;
    	for(int i=1;i<lim;i++)r[i]=(r[i>>1]>>1)|((i&1)<<l);
    	NTT(F,lim,1);NTT(G,lim,1);
    	for(int i=0;i<lim;i++)
    		F[i]=1ll*F[i]*G[i]%mod;
    	NTT(F,lim,-1);
    	int ans=0;
    	for(int i=0,p=1;i<=n;i++,p=(p<<1)%mod)
    		ans=(ans+1ll*p*fac[i]%mod*F[i]%mod)%mod;
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    设计模式-适配器模式(09)
    windows电脑使用技巧及常用CMD
    接口调用方法
    矩阵对角线和
    函数基础小结
    文件处理实战之购物车系统
    文件处理小结
    Python进阶实战之三级菜单
    Python进阶小结
    Python深浅拷贝
  • 原文地址:https://www.cnblogs.com/LeTri/p/10425479.html
Copyright © 2020-2023  润新知