BZOJ 4555 [Tjoi2016&Heoi2016]求和 NTT

39 篇文章 0 订阅
3 篇文章 0 订阅

题目在这里呀

题解

题目给你的那个递推式好废啊(没有一点用还是要百度通项)。
知道第二类斯特林数时只要带入原式展开可以发现卷积式,对它做NTT即可。
详细见学姐的博客
这篇博客讲的很清晰很具体,不会展开的话就看这篇吧qaq(不是我懒,是因为我也是看了这篇才会的啦ww)

//Suplex
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
#define N 100000+1000
using namespace std;
const int mod=998244353;
//f(i)=(1/i!)*sigma(i^n)
//g(i)=(1/i!)*(-1)^i
//F(j)=(j!)*2^j*sigma(f(j-k)*g(k))

int n,m,L;
ll ans,now,f[N+N+N],g[N+N+N],fac[N],inv[N+N+N],invv[N],fac2[N],w[N+N+N];

inline ll power(ll a,int b)
{
    ll mul=1;
    while(b){
        if(b & 1) mul=(mul*a) % mod;
        a=a*a % mod;
        b>>=1;
    }
    return mul;
}

inline ll mo(ll xx)
{
    if(xx>mod) return xx-mod;
    if(xx<0) return xx+mod;
    return xx;
}

void NTT(ll *a,int opt)
{
    for(int i=0,j=0;i<L;i++){
        if(i>j) swap(a[i],a[j]);
        for(int k=L>>1;(j ^= k)<k;k>>=1);
    }
    for(int len=2;len<=L;len<<=1){
        int l=len>>1;
        ll W=power(3,(mod-1)/len);
        for(int i=1;i<l;i++) w[i]=w[i-1]*W % mod;
        for(int i=0;i<L;i+=len)
            for(int j=0;j<l;j++){
                ll x=a[i+j],y=w[j]*a[i+j+l] % mod;
                a[i+j]=mo(x+y);a[i+j+l]=mo(x-y);
            }
    }
    if(opt==-1)
    {
        for(int i=1;i<L/2;i++) swap(a[i],a[L-i]);
    //  for(int i=0;i<L;i++) a[i]=a[i]*inv[L] % mod;
    }
}

int main()
{
    scanf("%d",&n);
    m=n<<1;w[0]=1;
    for(L=1;L<=m;L<<=1);
    fac[0]=1ll;
    for(int i=1;i<=n;i++) fac[i]=(fac[i-1]*(ll)i) % mod;
    fac2[0]=1ll;
    for(int i=1;i<=n;i++) fac2[i]=(fac2[i-1]+fac2[i-1]) % mod;
    inv[1]=1ll;
    for(int i=2;i<=L;i++) inv[i]=(ll)(mod-mod/i)*inv[mod % i] % mod;
    invv[0]=1ll;
    for(int i=1;i<=n;i++) invv[i]=invv[i-1]*inv[i] % mod;
    now=-1;f[0]=g[0]=1ll;
    for(int i=1;i<=n;i++){
        g[i]=now*invv[i] % mod;
        if(i==1) f[i]=(ll)n+1;
        else f[i]=invv[i]*(power(i,n+1)-1) % mod * inv[i-1] % mod;
        now=-now;
    }
    NTT(f,1);NTT(g,1);
    for(int i=0;i<=L;i++) f[i]=f[i]*g[i] % mod;
    NTT(f,-1);
    for(int i=0;i<=n;i++)
        ans=(ans+fac[i]*fac2[i] % mod * f[i] % mod * inv[L] % mod) % mod;
    ans=(ans+mod) % mod;
    printf("%lld\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值