Tjoi2016&Heoi2016 求和
我知道这题可以直接把第二类斯特林数展开后一遍NTT算出来(你们没看到我写的那篇博客么……),我只是想练一练分治NTT……
题目要求的是
\begin{equation}Ans=\sum_{i=0}^n\sum_{j=0}^i S(i,j)×2^j×(j!)\end{equation}
设
\begin{equation}A_i=\sum_{j=0}^i S(i,j)×2^j×(j!)\end{equation}
那么$A_i$的实际意义就是把n个小球放入任意多个不同盒子,每个盒子还有两种状态(你可以认为盒子有红色和蓝色两种)的方案数。
然后就不难写出$A_i$的递推式了:
\begin{equation}A_i=2\sum_{j=0}^i C_i^j A_j\end{equation}
显然这个递推式是可以直接分治NTT的,那么分治NTT裸上就好了,复杂度$O(n\log^2 n)$。
1 /************************************************************** 2 Problem: 4555 3 User: hzoier 4 Language: C++ 5 Result: Accepted 6 Time:3020 ms 7 Memory:3892 kb 8 ****************************************************************/ 9 #include<cstdio> 10 #include<cstring> 11 #include<algorithm> 12 using namespace std; 13 const int maxn=262200,p=998244353,g=3; 14 void NTT(int*,int,int); 15 int qpow(int,int,int); 16 int n,N=1,f[maxn],A[maxn],B[maxn],ans=0; 17 int main(){ 18 scanf("%d",&n); 19 while(N<=(n<<1))N<<=1; 20 f[0]=1; 21 for(int i=1;i<=n;i++)f[i]=(long long)f[i-1]*i%p; 22 for(int i=0;i<=n;i++){ 23 A[i]=qpow(f[i],p-2,p); 24 B[i]=A[i]; 25 if(i&1)A[i]=(p-A[i])%p; 26 if(i==1)B[i]=(long long)B[i]*(n+1)%p; 27 else B[i]=(long long)B[i]*((qpow(i,n+1,p)-1+p)%p)%p*qpow((i-1+p)%p,p-2,p)%p; 28 } 29 NTT(A,N,1); 30 NTT(B,N,1); 31 for(int i=0;i<N;i++)A[i]=(long long)A[i]*B[i]%p; 32 NTT(A,N,-1); 33 for(int i=0,pw=1;i<=n;i++,pw=(pw<<1)%p)ans=(ans+(long long)pw*f[i]%p*A[i]%p)%p; 34 printf("%d",ans); 35 return 0; 36 } 37 void NTT(int *A,int n,int tp){ 38 for(int i=1,j=0,k;i<n-1;i++){ 39 k=n; 40 do j^=(k>>=1);while(j<k); 41 if(i<j)swap(A[i],A[j]); 42 } 43 for(int k=2;k<=n;k<<=1){ 44 int wn=qpow(g,(tp>0?(p-1)/k:(p-1)/k*(long long)(p-2)%(p-1)),p); 45 for(int i=0;i<n;i+=k){ 46 int w=1; 47 for(int j=0;j<(k>>1);j++,w=(long long)w*wn%p){ 48 int a=A[i+j],b=(long long)w*A[i+j+(k>>1)]%p; 49 A[i+j]=(a+b)%p; 50 A[i+j+(k>>1)]=(a-b+p)%p; 51 } 52 } 53 } 54 if(tp<0){ 55 int inv=qpow(n,p-2,p); 56 for(int i=0;i<n;i++)A[i]=(long long)A[i]*inv%p; 57 } 58 } 59 int qpow(int a,int b,int p){ 60 int ans=1; 61 for(;b;b>>=1,a=(long long)a*a%p)if(b&1)ans=(long long)ans*a%p; 62 return ans; 63 }
233333333