1. 程式人生 > >解題:HEOI 2016 求和

解題:HEOI 2016 求和

題面

 我們需要知道這樣一個東西(大概叫 斯特林展開)

$S(i,j)=\frac{1}{j!}\sum\limits_{k=0}^{j}(-1)^k C_{j,k}(j-k)^i$

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=100005,mod=998244353;
 6 int a[4*N],b[4*N],rev[4*N],fac[N],inv[N];
 7 int
n,ni,G,Gi,pw,ans; 8 void exGCD(int a,int b,int &x,int &y) 9 { 10 if(!b) {x=1,y=0; return;} 11 exGCD(b,a%b,y,x),y-=a/b*x; 12 } 13 int Qpow(int x,int k) 14 { 15 if(!k) return 1; 16 if(k==1) return x; 17 int tmp=Qpow(x,k/2); 18 return k%2?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod;
19 } 20 int Inv(int x) 21 { 22 int xx,yy; 23 exGCD(x,mod,xx,yy); 24 return (xx%mod+mod)%mod; 25 } 26 void NTT(int *arr,int len,int typ) 27 { 28 for(int i=0;i<=len;i++) 29 if(rev[i]>i) swap(arr[rev[i]],arr[i]); 30 for(int i=2;i<=len;i<<=1) 31 { 32 int
lth=i>>1,ort=Qpow(~typ?G:Gi,(mod-1)/i); 33 for(int j=0;j<len;j+=i) 34 { 35 int ori=1,tmp; 36 for(int k=j;k<j+lth;k++,ori=1ll*ori*ort%mod) 37 { 38 tmp=1ll*ori*arr[k+lth]%mod; 39 arr[k+lth]=(arr[k]-tmp+mod)%mod; 40 arr[k]=(arr[k]+tmp)%mod; 41 } 42 } 43 } 44 if(typ==-1) 45 { 46 int ni=Inv(len); 47 for(int i=0;i<=len;i++) 48 arr[i]=1ll*arr[i]*ni%mod; 49 } 50 } 51 void Init() 52 { 53 scanf("%d",&n); 54 G=3,Gi=Inv(G),fac[0]=inv[0]=pw=1; 55 for(int i=1;i<=n;i++) 56 fac[i]=1ll*fac[i-1]*i%mod; 57 inv[n]=Inv(fac[n]); 58 for(int i=n-1;i;i--) 59 inv[i]=1ll*inv[i+1]*(i+1)%mod; 60 for(int i=0;i<=n;i++) 61 a[i]=(i%2)?mod-inv[i]:inv[i]; b[0]=1,b[1]=n+1; 62 for(int i=2;i<=n;i++) 63 b[i]=1ll*(Qpow(i,n+1)-1)*Inv(i-1)%mod*inv[i]%mod; 64 } 65 void Prework() 66 { 67 int len=1; while(len<=2*n+2) len<<=1; 68 for(int i=1;i<=len;i++) 69 rev[i]=(rev[i>>1]>>1)+(i&1)*(len>>1); 70 NTT(a,len,1),NTT(b,len,1); 71 for(int i=0;i<=len;i++) a[i]=1ll*a[i]*b[i]%mod; 72 NTT(a,len,-1); 73 } 74 int main() 75 { 76 Init(),Prework(); 77 for(int i=0;i<=n;i++,pw=pw*2%mod) 78 ans+=1ll*pw*fac[i]%mod*a[i]%mod,ans%=mod; 79 printf("%d",ans); 80 return 0; 81 }
View Code