解题:HEOI 2016 求和

Posted ydnhaha

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解题:HEOI 2016 求和相关的知识,希望对你有一定的参考价值。

题面

我们需要知道这样一个东西(大概叫 斯特林公式?)

$S(i,j)=frac{1}{j!}sumlimits_{k=0}^{j}(-1)^k C_j^k(j-k)^i$

那么就是推啊

$=sumlimits_{i=0}^nsumlimits_{j=0}^iS(i,j)*2^j*j!$

然后问题来了,因为后面还有$2^j$和$j!$,我们发现这里展开斯特林数也没用,所以我们要把它们甩出去

因为$j>i$时$S(i,j)==0$,所以让后面求和到$n$,然后前提$2^j$和$j!$

$=sumlimits_{i=0}^nsumlimits_{j=0}^nS(i,j)*2^j*j!$

$=sumlimits_{j=0}^n2^j*j!sumlimits_{i=0}^nS(i,j)$

展开斯特林数

$=sumlimits_{j=0}^n2^j*j!sumlimits_{i=0}^nfrac{1}{j!}sumlimits_{k=0}^{j}(-1)^k C_j^k(j-k)^i$

一般我们会把$C(j,k)$拆开来消掉前面的$frac{i}{j!}$

$=sumlimits_{j=0}^n2^j*j!sumlimits_{i=0}^nfrac{1}{j!}sumlimits_{k=0}^{j}(-1)^kfrac{j!}{k!(j-k)!}(j-k)^i$

$=sumlimits_{j=0}^n2^j*j!sumlimits_{i=0}^nsumlimits_{k=0}^{j}(-1)^kfrac{1}{k!(j-k)!}(j-k)^i$

那后面这个东西明显的分成了两部分:和$k$有关的和和$j-k$有关的

$=sumlimits_{j=0}^n2^j*j!sumlimits_{i=0}^nsumlimits_{k=0}^{j}frac{(-1)^k}{k!}frac{(j-k)^i}{(j-k)!}$

使用高中老师教给我们的等比数列求和公式

$=sumlimits_{j=0}^n2^j*j!sumlimits_{i=0}^nsumlimits_{k=0}^{j}frac{(-1)^k}{k!}frac{(j-k)^{i+1}-1}{(j-k-1)(j-k)!}$

这样和是一定的,所以用NTT卷出来后面的然后前面的$O(n)$求和就可以了

技术分享图片
 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

 

以上是关于解题:HEOI 2016 求和的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ4555][TJOI2016&HEOI2016]求和(分治FFT)

[HEOI2016/TJOI2016]求和

[HEOI2016/TJOI2016]求和

[HEOI2016]求和 sum

bzoj 4555 [Tjoi2016&Heoi2016]求和 NTT 第二类斯特林数 等比数列求和优化

[HEOI2016/TJOI2016]求和