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 }
View Code

好方法一会了。

从定义上出发,$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 }
View Code

 

posted @ 2018-02-27 16:15  Blue233333  阅读(252)  评论(0编辑  收藏  举报