BZOJ4555: [Tjoi2016&Heoi2016]求和
$n<=100000$求$\sum_{i=0}^{n}\sum_{j=0}^{i}s(i,j)*2^j*(j!)$,其中$S(i,j)$表示第二类斯特林数。
方法一:多项式求逆。不会。
方法二:
$S(i,j)=\frac{1}{j!}\sum_{k=0}^{j}(-1)^kC_j^k(j-k)^i$,代入得(这里由于j>i是S(i,j)=0因此j可以枚举到n)
$\sum_{i=0}^{n}\sum_{j=0}^{i}s(i,j)*2^j*(j!)$
$=\sum_{i=0}^{n}\sum_{j=0}^{n}2^j*(j!)*\frac{1}{j!}\sum_{k=0}^{j}(-1)^kC_j^k(j-k)^i$
$=\sum_{j=0}^{n}2^j\sum_{k=0}^{j}(-1)^kC_j^k\sum_{i=0}^{n}(j-k)^i$
$=\sum_{j=0}^{n}2^j*(j!)\sum_{k=0}^{j}\frac{(-1)^k}{k!}\frac{\sum_{i=0}^{n}(j-k)^i}{(j-k)!}$
后面俩卷积。搞定。
注意预处理时的边界情况。比如i=0,i=1,i=2之类的。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 //#include<map> 6 #include<math.h> 7 //#include<time.h> 8 //#include<complex> 9 #include<algorithm> 10 using namespace std; 11 12 int n,m,wei; 13 #define maxn 262222 14 const int mod=998244353,G=3; int rev[maxn]; 15 16 int powmod(int a,int b) 17 { 18 int ans=1; 19 while (b) 20 { 21 if (b&1) ans=1ll*ans*a%mod; 22 a=1ll*a*a%mod; b>>=1; 23 } 24 return ans; 25 } 26 27 void dft(int *a,int n,int type) 28 { 29 if (!rev[1]) for (int i=0;i<n;i++) 30 { 31 rev[i]=0; 32 for (int j=0;j<wei;j++) rev[i]|=((i>>j)&1)<<(wei-j-1); 33 } 34 for (int i=0;i<n;i++) if (i<rev[i]) {int t=a[i]; a[i]=a[rev[i]]; a[rev[i]]=t;} 35 for (int i=1;i<n;i<<=1) 36 { 37 int w=powmod(G,(mod-1)/(i<<1)); 38 if (type==-1) w=powmod(w,mod-2); 39 for (int j=0,p=i<<1;j<n;j+=p) 40 { 41 int t=1; 42 for (int k=0;k<i;k++,t=1ll*t*w%mod) 43 { 44 int tmp=1ll*t*a[j+k+i]%mod; 45 a[j+k+i]=(a[j+k]-tmp+mod)%mod; 46 a[j+k]=(a[j+k]+tmp)%mod; 47 } 48 } 49 } 50 if (type==-1) 51 { 52 int inv=powmod(n,mod-2); 53 for (int i=0;i<n;i++) a[i]=1ll*a[i]*inv%mod; 54 } 55 } 56 57 void ntt(int *a,int *b,int *c) 58 { 59 dft(a,n,1); dft(b,n,1); 60 for (int i=0;i<n;i++) c[i]=1ll*a[i]*b[i]%mod; 61 dft(c,n,-1); 62 } 63 64 int two[maxn],fac[maxn],inv[maxn],ni[maxn],g[maxn],h[maxn],f[maxn]; 65 int main() 66 { 67 scanf("%d",&n); 68 two[0]=1; for (int i=1;i<=n;i++) two[i]=(two[i-1]<<1)%mod; 69 fac[0]=1; for (int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod; 70 inv[n]=powmod(fac[n],mod-2); for (int i=n;i;i--) inv[i-1]=inv[i]*1ll*i%mod; 71 ni[1]=1; for (int i=2;i<=n;i++) ni[i]=ni[mod%i]*1ll*(mod-mod/i)%mod; 72 73 g[0]=1; g[1]=n+1; g[2]=(powmod(2,n+1)-1)*1ll*ni[2]%mod; 74 for (int i=3;i<=n;i++) g[i]=1ll*(mod/(i-1)*1ll*ni[mod%(i-1)]%mod)*(mod+1-powmod(i,n+1))%mod*inv[i]%mod; 75 for (int i=0;i<=n;i++) h[i]=1ll*((i&1)?mod-1:1)*inv[i]%mod; 76 77 m=n+n; for (n=1,wei=0;n<=m;n<<=1,wei++); 78 ntt(h,g,f); m>>=1; 79 int ans=0; 80 for (int i=0;i<=m;i++) ans=(ans+1ll*two[i]*fac[i]%mod*f[i]%mod)%mod; 81 printf("%d\n",ans); 82 return 0; 83 }
好方法一会了。
从定义上出发,$s(i,j)$是$i$个数分成$j$个集合,再乘个$j!$就排列,再乘个$2^j$就染黑白。
OK可以递推了,枚举最后一个集合是谁,$f(i)=\sum_{j=0}^{i}s(i,j)*2^j*(j!)=\sum_{j=1}^{i}2C_i^jf(i-j)=\sum_{j=1}^{i}\frac{2*i!*f(i-j)}{j!(i-j)!}$
$i!$提出来丢左边,$\frac{f(i)}{i!}=\sum_{j=1}^{i}\frac{2}{j!}\frac{f(i-j)}{(i-j)!}$,一卷积。
令$g(i)=\frac{f(i)}{i!}$,$h(i)=\frac{2}{i!}$,要卷积就来生成函数吧,现在$g(x)$,$h(x)$表示各自的生成函数。
打住!这里卷积不希望有$h(0)g(i)$这项!!那钦定$h(x)$常数项为0.
等等$g(x)$的常数项是1啊!那就$g=g*h+1$。
于是$g=\frac{1}{1-h}$。
搞定。求(1-h)的逆即可。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 //#include<map> 6 #include<math.h> 7 //#include<time.h> 8 //#include<complex> 9 #include<algorithm> 10 using namespace std; 11 12 int n,m,wei; 13 #define maxn 262222 14 const int mod=998244353,G=3; int rev[maxn]; 15 16 int powmod(int a,int b) 17 { 18 int ans=1; 19 while (b) 20 { 21 if (b&1) ans=1ll*ans*a%mod; 22 a=1ll*a*a%mod; b>>=1; 23 } 24 return ans; 25 } 26 27 void dft(int *a,int n,int type) 28 { 29 int wei=-1,tnt=n; 30 while (tnt) wei++,tnt>>=1; 31 for (int i=0;i<n;i++) 32 { 33 rev[i]=0; 34 for (int j=0;j<wei;j++) rev[i]|=((i>>j)&1)<<(wei-j-1); 35 } 36 for (int i=0;i<n;i++) if (i<rev[i]) {int t=a[i]; a[i]=a[rev[i]]; a[rev[i]]=t;} 37 for (int i=1;i<n;i<<=1) 38 { 39 int w=powmod(G,(mod-1)/(i<<1)); 40 if (type==-1) w=powmod(w,mod-2); 41 for (int j=0,p=i<<1;j<n;j+=p) 42 { 43 int t=1; 44 for (int k=0;k<i;k++,t=1ll*t*w%mod) 45 { 46 int tmp=1ll*t*a[i+j+k]%mod; 47 a[j+k+i]=(a[j+k]-tmp+mod)%mod; 48 a[j+k]=(a[j+k]+tmp)%mod; 49 } 50 } 51 } 52 if (type==-1) 53 { 54 int inv=powmod(n,mod-2); 55 for (int i=0;i<n;i++) a[i]=1ll*a[i]*inv%mod; 56 } 57 } 58 59 int fac[maxn],inv[maxn],h[maxn],g[maxn],tmp[maxn]; 60 void nee(int *a,int n,int *ans) 61 { 62 if (n==1) {ans[0]=powmod(a[0],mod-2); return;} 63 nee(a,n>>1,ans); 64 for (int i=0;i<(n>>1);i++) tmp[i]=a[i]; for (int i=(n>>1);i<n;i++) tmp[i]=0; 65 dft(ans,n,1); dft(tmp,n,1); 66 for (int i=0;i<n;i++) ans[i]=((ans[i]+ans[i]-1ll*ans[i]*ans[i]%mod*tmp[i]%mod)+mod)%mod; 67 dft(ans,n,-1); for (int i=n>>1;i<n;i++) ans[i]=0; 68 } 69 70 int main() 71 { 72 scanf("%d",&n); 73 fac[0]=1; for (int i=1;i<=n;i++) fac[i]=fac[i-1]*1ll*i%mod; 74 inv[n]=powmod(fac[n],mod-2); for (int i=n;i;i--) inv[i-1]=1ll*inv[i]*i%mod; 75 h[0]=1; for (int i=1;i<=n;i++) h[i]=(mod+mod-inv[i]-inv[i])%mod; 76 77 m=n+n; for (n=1,wei=0;n<=m;n<<=1,wei++); 78 nee(h,n,g); m>>=1; 79 int ans=0; 80 for (int i=0;i<=m;i++) ans=(ans+1ll*fac[i]*g[i])%mod; 81 printf("%d\n",ans); 82 return 0; 83 }