一我的的高三樓:多項式卷積,生成函數

Description:數組

一天的學習快要結束了,高三樓在晚自習的時候恢復了寧靜。
不過,HSD 桑還有一些做業沒有完成,他須要在這個晚自習寫完。好比這道數學題:ide

一、給出一個數列,求它的前i項和$S_i$函數

HSD 桑擅長數學,很快就把這題秒了……
然而還有第二題:學習

二、若是把上一問的前n項和當作一個新數列,請求出它的i項和ui

 

看完第二題,還有第三題……HSD 桑已經預感到狀況不妙了。
HSD 桑大體看了看題,發現有些規律。其實就是在求 spa

次前綴和。若是咱們借用函數迭代的標記,就是在求 $S_n^{(k)}$
HSD 桑還有不少做業要寫,請你幫助他完成這項做業。$mod \ 998244353$
code

$n \leq 100000 , k \leq 2^{63}$blog

時限:100msip

 

廢話:數學

挺好的一道題。skyh一直在跟我說LNC給他頹了題解因而我也來作了。

然而我並不會因而打表找規律直接發現$O(n\ log\ n)$的式子而後就完了。

可是實際上丟了一箇中間步驟$O(n\ log \ n log \  k)$

 

題解:

設咱們要求的$S_n^{(k)}$的生成函數$F_{(k)}(x)=\sum\limits_{i=0}^{n-1} S_{i+1}^{(k)} x^i$

而後考慮前綴和的過程,就是每一項都累加前面的全部項,也能夠理解爲每一個數都爲後面的項作貢獻

那麼感受好像已經有卷積形式了,讓咱們吧這個「貢獻」方式也寫成生成函數:

$G(x)=\sum\limits_{i=0}^{n-1}x^i$

而後按照貢獻規則咱們能知道$F_{(k+1)}(x)=F_{(k)}(x) \times G(x)$

生成函數就是多項式了,這很卷積,因而咱們用快速冪的方式分別卷一下$F$和$G$就行。

這樣的複雜度是$O(n\ log \ n log \  k)$的。時限故意卡掉了。

考慮這個$G$函數的具體意義:在$F$函數的表上往下走一步的同時往右走了若干步

根據範德蒙恆等式(我仍是喜歡叫棗樹定理),組合數能夠合併成一個

那麼最後咱們能知道它的答案就是$f[i]=\sum\limits_{j=1}^{i} C_{k-1+i-j}^{k-1}  \times g[j]$

其中$g$是原數組,$f$是答案數組。

而後這是一個比較明顯的卷積。至於怎麼求組合數?

線性遞推一乘一除就行了,k太大要及時取模。

 1 #include<cstdio>
 2 #define mod 998244353
 3 #define int long long
 4 int n,C[300000],x[300000],k,bin=1,rev[300000],INV;
 5 int pow(int b,int t,int a=1){for(;t;t>>=1,b=b*b%mod)if(t&1)a=a*b%mod;return a;}
 6 void NTT(int *a,int opt){
 7     for(int i=0;i<bin;++i)if(i<rev[i])a[i]^=a[rev[i]]^=a[i]^=a[rev[i]];
 8     for(int mid=1,wn;mid<bin;mid<<=1){
 9         wn=pow(3,(mod-1)/2/mid*opt+mod-1);
10         for(int i=0;i<bin;i+=mid<<1)
11             for(int j=0,w=1;j<mid;++j,w=w*wn%mod){
12                 int x=a[i+j],y=a[i+j+mid]*w%mod;
13                 a[i+j]=(x+y)%mod;a[i+j+mid]=(x-y+mod)%mod;
14             }
15     }
16     if(opt==-1)for(int i=0;i<bin;++i)a[i]=a[i]*INV%mod;
17 }
18 main(){
19     scanf("%lld%lld",&n,&k);k%=mod;
20     while(bin<=n<<1)bin<<=1; INV=pow(bin,mod-2);
21     for(int i=1;i<bin;++i)rev[i]=rev[i>>1]>>1|(i&1)*bin>>1;
22     for(int i=0;i<n;++i)scanf("%lld",&x[i]);
23     C[0]=1;
24     for(int i=1;i<n;++i)C[i]=C[i-1]*(k+i-1)%mod*pow(i,mod-2)%mod;
25     NTT(C,1);NTT(x,1);
26     for(int i=0;i<bin;++i)x[i]=x[i]*C[i]%mod;
27     NTT(x,-1);
28     for(int i=0;i<n;++i)printf("%lld\n",x[i]);
29 }
View Code
相關文章
相關標籤/搜索