luogu P4091 [HEOI2016/TJOI2016]求和
阿新 • • 發佈:2021-06-30
題面傳送門
並不覺得這道題有黑題難度。
首先因為當\(j>i\)時\(S(i,j)=0\)所以這個東西其實可以寫成\(\sum\limits_{j=0}^{n}{j!\times 2^j\sum\limits_{i=0}^{n}{S(i,j)}}\)
我們設\(H(j)=\sum\limits_{i=0}^{n}{S(i,j)}\)就可以\(O(n)\)算這個式子的值了。
上面那個式子我們考慮用第二類斯特林數的通項公式變成\(\sum\limits_{i=0}^{n}{\sum\limits_{k=0}^{j}{\frac{(-1)^k(j-k)^i}{k!(j-k)!}}}\)
交換求和順序變成\(\sum\limits_{k=0}^{j}{\frac{(-1)^k}{k!(j-k)!}\sum\limits_{i=0}^{n}{(j-k)^i}}\)
設\(F(x)=\sum\limits_{i=0}^{n}{x^i}\)這個顯然可以等比數列\(O(1)\)求。
那麼原式就變成\(\sum\limits_{k=0}^{j}{\frac{(-1)^k}{k!(j-k)}F(j-k)}\)
然後顯然卷一下就可以\(O(nlogn)\)求了。
code:
#include<bits/stdc++.h> #define I inline #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define abs(x) ((x)>0?(x):-(x)) #define re register #define ll long long #define db double #define N 300000 #define M 200000 #define mod 998244353 #define eps (1e-7) #define U unsigned int #define IT set<ques>::iterator #define Gc() getchar() #define Me(x,y) memset(x,y,sizeof(x)) using namespace std; int n,m,tr[N+5];ll F[N+5],G[N+5],Ans,invn,ToT=1,frc[N+5],H[N+5],inv[N+5]; I ll mpow(ll x,int y=mod-2){ll ans=1;while(y) (y&1)&&(ans=ans*x%mod),y>>=1,x=x*x%mod;return ans;}const ll Gs=3,invG=mpow(Gs); I void swap(ll &x,ll &y){x^=y^=x^=y;} I void NTT(ll *A,int n,int flag){ int i,j,h;ll now,key,pus;for(i=0;i<n;i++) i<tr[i]&&(swap(A[i],A[tr[i]]),0); for(i=2;i<=n;i<<=1){ for(key=mpow(flag?Gs:invG,(mod-1)/i),j=0;j<n;j+=i){ for(now=1,h=j;h<j+i/2;h++)pus=now*A[h+i/2]%mod,A[h+i/2]=(A[h]-pus+mod)%mod,A[h]=(A[h]+pus)%mod,now=now*key%mod; } } } int main(){ freopen("1.in","r",stdin); re int i;scanf("%d",&n);frc[0]=inv[0]=1;for(i=1;i<=n;i++) frc[i]=frc[i-1]*i%mod,inv[i]=mpow(frc[i]); for(i=0;i<=n;i++)F[i]=(i&1)?(mod-inv[i]):(inv[i]);H[0]=1;H[1]=n+1;for(i=2;i<=n;i++) H[i]=(mpow(i,n+1)-1)*mpow(i-1)%mod; for(i=0;i<=n;i++) G[i]=H[i]*inv[i]%mod;for(m=1;m<=n*2;m<<=1);for(i=0;i<m;i++)tr[i]=(tr[i>>1]>>1)|((i&1)?(m>>1):0); NTT(F,m,1);NTT(G,m,1);for(i=0;i<m;i++)F[i]=F[i]*G[i]%mod;NTT(F,m,0); for(i=0;i<=n;i++) Ans+=ToT*frc[i]%mod*F[i]%mod,ToT=ToT*2%mod;printf("%lld\n",Ans%mod*mpow(m)%mod); }