P4091 [HEOI2016/TJOI2016]求和

首先发现j是可以枚举到n的,因为j>i时s(i,j)为0。

把第二类斯特林数按照容斥的定义转换一下。

由于第二类斯特林数是一个卷积的形式,可以枚举i后ntt求解,复杂度O(n^2logn)

变换一下枚举的顺序,把i移到最内层。

发现可以预处理一下sigema i0+i1+i2+i3.....i^n然后就o(nlogn)了。

#include<iostream>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#define N 1100000
#define L 1100000
#define eps 1e-7
#define inf 1e9+7
#define db double
#define ll long long
#define ldb long double
using namespace std;
inline ll read()
{
    char ch=0;
    ll x=0,flag=1;
    while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*flag;
}
const ll d=3,mo=998244353;
ll ksm(ll x,ll k)
{
    ll ans=1;
    while(k)
    {
        if(k&1)ans=1ll*ans*x%mo;
        k>>=1;
        x=1ll*x*x%mo;
    }
    return ans;
}
ll inv(ll x){return ksm(x,mo-2);}
ll rev[N];
void ntt(ll *f,ll n,ll flag)
{
    for(ll i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)+(i&1)*(n>>1);
    for(ll i=0;i<n;i++)if(i<rev[i])swap(f[i],f[rev[i]]);
    for(ll k=2,kk=1;k<=n;k<<=1,kk<<=1)
    {
        ll wn=ksm(d,(mo-1)/k);
        if(flag==-1)wn=inv(wn); 
        for(ll i=0;i<n;i+=k)
        for(ll j=0,w=1;j<kk;j++,w=1ll*w*wn%mo)
        {
            ll t=1ll*w*f[i+j+kk]%mo;
            f[i+j+kk]=(f[i+j]-t+mo)%mo;
            f[i+j]=(f[i+j]+t)%mo;
        }
    }
    if(flag==-1)
    {
        ll k=inv(n);
        for(ll i=0;i<n;i++)f[i]=(f[i]*k)%mo;
    }
}
ll a[N],b[N];
void mul(ll len)
{
    for(ll i=len;i<2*len;i++)a[i]=b[i]=0;
    ntt(a,2*len,+1);ntt(b,2*len,+1);
    for(ll i=0;i<2*len;i++)a[i]=1ll*a[i]*b[i]%mo;
    ntt(a,2*len,-1);
}
ll f[N],fac[N];
int main()
{
    ll n,len=read();
	for(n=1;n<=len+1;n<<=1);
	for(ll i=0;i<=len;i++)
	{
		fac[i]=i?((fac[i-1]*i)%mo):1;
		if(i==0)f[i]=1;
		else if(i==1)f[i]=len+1;
		else f[i]=(ksm(i,len+1)-1)*inv((i-1))%mo;
	}
	for(ll i=0;i<=len;i++)
	{
		a[i]=(ksm(-1,i)*inv(fac[i])+mo)%mo;
		b[i]=f[i]*inv(fac[i])%mo;
	}
	mul(n);
	ll ans=0;
	for(ll i=0;i<=len;i++)ans=(ans+((ksm(2,i)*fac[i]%mo*a[i])%mo))%mo;
	printf("%lld",(ans%mo+mo)%mo);
    return 0;
}
原文地址:https://www.cnblogs.com/Creed-qwq/p/10211460.html