P4091 [HEOI2016/TJOI2016]求和(第二类斯特林数,ntt)
Posted azznaz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4091 [HEOI2016/TJOI2016]求和(第二类斯特林数,ntt)相关的知识,希望对你有一定的参考价值。
题面:https://www.luogu.org/problem/P4091
题解:\[\beginarrayl
f(n) = \sum\limits_i = 0^n \sum\limits_j = 0^i \rmS(i,j) \cdot 2^\rmj \cdot j! \\
= \sum\limits_i = 0^n \sum\limits_j = 0^n \rmS(i,j) \cdot 2^\rmj \cdot j!
\endarray\]
把公式\[S(n,m) = \frac\sum\limits_i = 0^m ( - 1)^i\rm\cdotC_m^i \rm\cdot(m - i)^nm!\]带进去
则\[\rm\backslash begin\ array\ \ l\ n\backslash begin\ array\ \ *\ 20\ \ l\ \ f(n) = \sum\limits_i = 0^n \sum\limits_j = 0^n \rmS(i,j) \cdot 2^\rmj \cdot j! = \sum\limits_i = 0^n \sum\limits_j = 0^n \sum\limits_k = 0^j \frac( - 1)^kk! \cdot \frac(j - k)^i(j - k)! \cdot \rm2^\rmj\rm\cdotj! \rmn\ = \sum \rm\_j = \rm\^n\rm \ 2^j\rm\cdotj!\sum \rm\_k = 0\rm\^j\rm \ \sum \rm\_i = 0\rm\^n\rm \ \frac( - 1)^kk! \cdot \frac(j - k)^i(j - k)! = \sum \rm\_j = \rm\^n\rm \ 2^j\rm\cdotj!\sum \rm\_k = 0\rm\^j\rm \ \backslash frac\ \ \ ( - 1)\rm\^\ \^k\rm\ \ \ \ k! \cdot \rm\ \frac\sum\limits_i = 0^n (j - k)^i (j - k)!\rm\ \ \ \ \ n\backslash end\ array\ \backslash \backslash = \sum \rm\_j = \rm\^n\rm \ 2^j\rm\cdotj!\sum \rm\_k = 0\rm\^j\rm \ \backslash frac\ \ \ ( - 1)\rm\^\ \^k\rm\ \ \ \ k! \cdot \rm\ \frac(j - k)^n + 1 - 1(j - k)! \cdot (j - k - 1)\rm\ n\backslash end\ array\ \]
令\[\beginarrayl
h(x) = \frac( - 1)^xx!\\
g(x) = \fracx^n + 1 - 1x!\rm\cdot(x - 1)
\endarray\]
后面的就是这两个的卷积,直接上ntt就行了
#include<bits/stdc++.h> #define ms(x) memset(x,0,sizeof(x)) #define sws ios::sync_with_stdio(false) using namespace std; typedef long long ll; const int maxn=5e5+5; const double pi=acos(-1.0); const ll mod=998244353;///通常情况下的模数, const ll g=3;///模数的原根998244353,1004535809,469762049 ll qpow(ll a,ll n,ll p) ll ans=1; while(n) if(n&1) ans=ans*a%p; n>>=1; a=a*a%p; return ans; int rev[maxn]; void ntt(ll a[],int n,int len,int pd) rev[0]=0; for(int i=1;i<n;i++) rev[i]=(rev[i>>1]>>1 | ((i&1)<<(len-1))); if(i<rev[i]) swap(a[i],a[rev[i]]); for(int mid=1;mid<n;mid<<=1) ll wn=qpow(g,(mod-1)/(mid*2),mod);///原根代替单位根 if(pd==-1) wn=qpow(wn,mod-2,mod);///逆变换则改成逆元 for(int j=0;j<n;j+=2*mid) ll w=1; for(int k=0;k<mid;k++) ll x=a[j+k],y=w*a[j+k+mid]%mod; a[j+k]=(x+y)%mod; a[j+k+mid]=(x-y+mod)%mod; w=w*wn%mod; if(pd==-1) ll inv=qpow(n,mod-2,mod); for(int i=0;i<n;i++) a[i]=a[i]*inv%mod; ll a[maxn],b[maxn],c[maxn]; void solve(int n,int m) int len=0,up=1; while(up<=n+m) up<<=1,len++; ntt(a,up,len,1); ntt(b,up,len,1); for(int i=0;i<up;i++) c[i]=1ll*a[i]*b[i]%mod; ntt(c,up,len,-1); ll fa[maxn]; int main() int n,m; sws; cin>>n; fa[0]=1; a[0]=1; b[0]=1; for(int i=1;i<=n;i++) fa[i]=1ll*fa[i-1]*i%mod; int t=(i&1)==1?-1:1; a[i]=(t*qpow(fa[i],mod-2,mod)+mod)%mod; if(i==1) b[1]=n+1; else b[i]=(qpow(i,n+1,mod)-1+mod)%mod*qpow(1ll*(i-1)*fa[i]%mod,mod-2,mod)%mod; solve(n,n); ll ans=0; for(ll i=0;i<=n;i++) ans=(ans+qpow(2,i,mod)*fa[i]%mod*c[i]%mod)%mod; cout<<ans<<endl;
以上是关于P4091 [HEOI2016/TJOI2016]求和(第二类斯特林数,ntt)的主要内容,如果未能解决你的问题,请参考以下文章