传送门
题解:
现在拿到洛谷rank1,BZOJrank1,LOJrank1。
首先这道题可以多项式求逆或者直接卷积做,复杂度都是 O ( n log n ) O(n\log n) O(nlogn)。
先推式子,根据第二类斯特林数通项公式: S n , k = ∑ i = 0 k ( − 1 ) i ( k − i ) n i ! ( k − i ) ! S_{n,k}=\sum_{i=0}^k\frac{(-1)^i(k-i)^n}{i!(k-i)!} Sn,k=∑i=0ki!(k−i)!(−1)i(k−i)n,直接代入可以得到:
A n s = ∑ i = 0 n ∑ j = 0 n 2 j j ! S i , j = ∑ i = 0 n ∑ j = 0 i 2 j ∑ k = 0 j ( j k ) ( − 1 ) j − k k i = ∑ j = 0 n ∑ k = 0 j ( − 1 ) j − k ( j k ) 2 j k n + 1 − 1 k − 1 = ∑ k = 0 n k n + 1 − 1 k − 1 ∑ j = k n ( − 1 ) j − k ( j k ) 2 j \begin{aligned} Ans=&\sum_{i=0}^n\sum_{j=0}^n2^jj!S_{i,j}\\ =&\sum_{i=0}^n\sum_{j=0}^i2^j\sum_{k=0}^j{j\choose k}(-1)^{j-k}k^i\\ =&\sum_{j=0}^n\sum_{k=0}^j(-1)^{j-k}{j\choose k}2^j\frac{k^{n+1}-1}{k-1}\\ =&\sum_{k=0}^n\frac{k^{n+1}-1}{k-1}\sum_{j=k}^{n}(-1)^{j-k}{j\choose k}2^j \end{aligned} Ans====i=0∑nj=0∑n2jj!Si,ji=0∑nj=0∑i2jk=0∑j(kj)(−1)j−kkij=0∑nk=0∑j(−1)j−k(kj)2jk−1kn+1−1k=0∑nk−1kn+1−1j=k∑n(−1)j−k(kj)2j
到这里很多人就直接做卷积了,但是观察一下这个东西: f ( k ) = ∑ j = 0 n ( − 1 ) j − k ( j k ) 2 j f(k)=\sum_{j=0}^{n}(-1)^{j-k}{j\choose k}2^j f(k)=j=0∑n(−1)j−k(kj)2j
感觉这东西可以递推。
然而实际上这东西真的可以递推。
先orz EI 为敬。这道题最早的线性做法就是EI提出来的:EI的blog。
我的题解就直接咕咕咕了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
cs int mod=998244353;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return r>=mod?r%mod:r;}
inline int power(int a,int b,int res=1){
for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));
return res;
}
inline void Inc(int &a,int b){(a+=b)>=mod&&(a-=mod);}
inline void Dec(int &a,int b){(a-=b)<0&&(a+=mod);}
inline void Mul(int &a,int b){a=mul(a,b);}
int n;
cs int P=2e5+5;
int pw[P];
int pr[P],pcnt;
bool mark[P];
int c[P],inv[P];
inline void linear_sieves(int lim){
pw[1]=1;
for(int re i=2;i<=lim;++i){
if(!mark[i]){
pw[i]=power(i,n+1);
pr[++pcnt]=i;
}
for(int re j=1;i*pr[j]<=lim;++j){
mark[i*pr[j]]=true;
pw[i*pr[j]]=mul(pw[i],pw[pr[j]]);
if(i%pr[j]==0)break;
}
}
inv[1]=inv[0]=1;c[0]=1,c[1]=n+1;
for(int re i=2;i<=lim;++i)inv[i]=mul(inv[mod%i],mod-mod/i);
for(int re i=2;i<=lim;++i)c[i]=mul(c[i-1],mul(n-i+2,inv[i]));
}
int a[P],ans;
signed main(){
scanf("%d",&n);
linear_sieves(n+1);
for(int re i=0;i<=n;++i)a[i]=((n-i)&1)?mod-c[i]:c[i];
for(int re i=0;i<=n;++i)Mul(a[i],pw[2]);++a[0];
int p=mul(inv[3],2);
for(int re i=1;i<=n;++i)Inc(a[i],mul(a[i-1],p));
ans=add(a[0],mul(a[1],n+1));
for(int re i=2;i<=n;++i)Inc(ans,mul(mul(pw[i]-1,inv[i-1]),a[i]));
std::cout<<mul(ans,inv[3])<<"\n";
return 0;
}