求混合揹包(某一體積的物品可能有無限個也可能有有限個),得到體積和爲1...n的方案數。
熱身題。
如果一個體積爲v的物品有無限個,那麼其關於體積的普通生成函數爲∑i=0xvi=1−xv1
如果一個體積爲v的物品有K個,那麼其關於體積的普通生成函數爲∑i=0Kxvi=1−xv1−xv(K+1)
將這些生成函數乘起來即可得到答案的生成函數。
發現總項數可能達到n2不能直接上多項式乘法,可以考慮對每個式子取ln求和後求exp。
ln(1−x)泰勒展開可以得到爲∑i=1i−xi
所以對於ln1−xv1=−ln1−xv=∑i=1ixiv
ln1−xv1−xv(K+1)=∑i=1ixiv−∑i=1ixiv(K+1)
求出xiv中v=v0的係數和後即可O(nlnn)求和得到ln後的式子求和的生成函數。
代碼
社論
fk(x)=i=1∑x−1fk(i)+xk,fk(1)=1
這個式子是一個 n階遞推,既不是齊次也不是線性。
我們可以化一下式子變成常係數非齊次線性遞推。
fk(x)=fk(x−1)+(i=1∑x−2fk(i)+(x−1)k)+xk−(x−1)k=2fk(x−1)+xk−(x−1)k
這是個一階常係數非齊次線性遞推。
我們知道如果是齊次的話,因爲這個遞推式只有一階,第n項可以用遞推式的特徵根的n次方之類用快速冪解決。
變成齊次的方法很簡單,
構造遞推式gk(x)=2gk(x−1)−xk+(x−1)k
所以(fk(x)+gk(x))=2(fk(x−1)+gk(x−1))。
我們求的fk(x)=2x−1(fk(1)+gk(1))−gk(n)
考慮到我們需要的gk(x)只需要滿足一個遞推式,發現有且僅有一個k−1次多項式gk(x)滿足這個方程。
也就是說gk(x)可以是一個k−1次多項式。
那麼我們只需要求出gk(0...k−1)即可拉格朗日插值得到gk(n),從而算出fk(n)。
分別求出 0...k的k次方後,可以通過假設gk(0)遞推得到gk(k),然後通過拉格朗日插值得到gk(k)的另一個表達式,解出gk(0)即可。
Code
社論
容易發現這個順序其實類似於樹的拓撲序反過來。
當兩個初始點重合的時候就是求樹的拓撲序計數。
經典結論:答案爲∏i in treeszin!,其中szi是以初始黑點爲根時i的子樹的大小。
當兩個初始點不重合時,新建一個點s,將初始點和s連邊。
那麼我們將會得到一顆基環樹,枚舉環上的一條邊割掉,我們就可以把問題看做以s爲初始黑點求樹的拓撲序計數。
考慮割掉的這條邊,它左右兩邊的點中一定恰好有一個是環上最後一個被染成紅色的點,所以對於一種情況有兩種可能的割邊(最後一個被染成紅色的點左右有兩條邊),所以最後答案要÷2。
然後在兩個初始黑點中選一個爲根求出每個點的子樹大小,其中兩個初始黑點間的鏈的每個點的子樹大小依次記爲c1,c2...cn,再在左邊加一個c0=0,注意這裏c1...cn是遞增的。
那麼∣ci−cj∣在i>j時的意義就是在j→j+1這條鏈斷開時的i的子樹大小。
在i<j時的意義就是在j→j+1這條鏈斷開時的i+1的子樹大小。
所以在斷開j→j+1時的鏈上的∏sz=∏i!=j∣ci−cj∣,不在鏈上的預處理即可。
那麼我們只需要求∑j∏i!=j∣ci−cj∣1,發現這個東西和多項式快速插值的第一部分一模一樣。
具體的設F(x)=∏j∣x−cj∣,有∏i!=j∣ci−cj∣=x−ciF(x)∣∣∣x=ci
因爲F(ci)=(ci−ci)=0用洛必達法則,有:
∏i!=j∣ci−cj∣=F(ci)′
分治 FFT後求導套多點求值即可。
Code
社論
容斥做法:
枚舉有具體k列放了兩顆石子,具體的2n−2k列放了一顆石子的方案數爲Sk。
ans=k=0∑n(km)(2n−2km−k)Sk
求Sk,考慮容斥掉同一行的兩顆石子不能在同一列這個限制。
Sk=2n+k1i=0∑k(in)(ik)(−1)ii!2i(2n−2i)!
這裏枚舉的i是同一行的兩顆石子在同一列的次數。
統計時將同一行的兩個石子看做不同,放在同一列的兩個石子先後有順序,這樣統計2n−2i個石子放入剩下還空着的列時可以直接寫(2n−2i)!,相對應的需要在外面÷2n÷2k(有k列可以放兩個石子)。
i!表示這i行都分別有兩個重合的石子,將他們分配給i列的方案,2i是因爲這兩個石子之間有順序。
Sk=2n+kn!k!i=0∑k(k−i)!1i!(n−i)!(−2)i(2n−2i)!
就可以卷積求出Sk,然後直接求得答案了。
還有一種多項式exp但是不寫exp的推法,本質應該有點類似,具體可以看上面的博客。
Code
社論
dp1:fi,j=fi−1,j+fi−1,j−1(ai+j),fi,j表示前i個數選了j數的貢獻和。
發現這個dp我不太會做。
換一下定義:fi,j表示前i個數選了i−j個數的貢獻和。
dp2:fi,j=fi−1,j−1+fi−1,j(ai+i−j)=fi−1,j−1−jfi−1,j+fi−1,j(ai+i)
考慮組合意義(和第二類斯特林數相似):對於每個i我們有三種選擇,
不選,代價×(ai+i),
選,加入前面j個組中的一個,代價×(−j),
選,新建一個組,代價無變化。
不選i個的代價可以用分治FFT求∏i=1n(x+ai+i)
選i個的代價,可以先考慮選一組的指數生成函數是−(e−x−1),(ex−1)是非空集合帶標號的指數生成函數,我們這裏除了第一個數,別的數加入還需要×−1,所以是−(e−x−1)。
那麼選 i個的代價的生成函數就是exp(1−e−x),注意是指數生成函數還需要除階乘。
然後將選和不選的生成函數卷積一下求xn項即可。
Code
福利題快速冪模板題
單位根反演:k1∑i=0k−1wkij=[k∣j]
當wkj=1時,即[k∣j]時,原式=kk=1
否則原式=k(1−wkj)1−wkkj=0
所以對於此題:∑i=0n[k∣i](in)=k1∑i=0n∑j=0k−1wkij(in)
=k1∑j=0k−1∑i=0nwkij(in)=k1∑j=0k−1(1+wkj)n
此題模數很友好,求出單位根後快速冪即可。
Code
設fu,i,0/1表示u子樹內選了i個點,其中u選沒選爲第三維的答案,
那麼樹鏈剖分後建出全局平衡二叉樹,對於虛兒子到父親的轉移即爲fu的分治FFT。
對於重兒子到父親,對重鏈分治,對於每一邊求出gi,0/1,0/1表示重鏈的某部分即下方的虛子樹,頭是否被選爲第二維,尾是否被選爲第三維。
對重鏈分治的時候可以按照下面子樹的sz分治而非對半分治,可以優化常數。
O(nlog3n)很好證明。
但是有人說這樣寫是O(nlog2n)的
Code
F(x)=∑i=0i!2(2i)xi有標號無向圖數量。
D(x)=ϑlnF(x)=[lnF(x)′]x即有根有標號聯通無向圖數量。
B(x)=∑i=1i!bi+1xi,bi爲i個點的無根有標號點雙連通圖數量。
那麼一個有根有標號聯通無向圖的根節點周圍可以掛若干個包含根的點雙,掛一個大小爲i+1的點雙,那麼除了根以外的i個點,每個點刪去和該點雙其他點的連邊後的連通塊是一個有根有標號聯通無向圖。
D(x)=xexp[∑i=1i!bi+1D(x)i]=xexpB[D(x)]
假設G[D(x)]=x即他們互爲複合逆。
那麼D(G(x))=G(x)expB[D(G(x))]
也即:x=G(x)expB(x)
B(x)=lnG(x)x
令lnxD(x)=C(x)
則有C(G(x))=lnG(x)x=B(x)
又根據擴展拉格朗日反演可以得到:
[xn]B(x)=[xn]C(G(x))=[xn−1]nD(x)nC(x)′xn=[xn−1]nC(x)′×(D(x)x)n=[xn−1]nC(x)′exp(−nlnxD(x))=[xn−1]nC(x)′exp(−nC(x))
首先可以看到
發現這個條件讓你可以直接多次拉格朗日反演求出大小∈S的所有點雙連通圖的方案數,設他的生成函數爲C(x)。
然後和點雙聯通圖計數一樣的方法設答案爲F(x)。
那麼考慮包含根的點雙,把這些點雙的邊刪掉之後,所有的點都可以掛一個我們正在求的圖也即F(x),然後自由組合。
所以可以得到方程:
F(x)=xexpC(F(x))
發現有:
expC(F(x))F(x)=x
所以F(x)和expC(x)x互爲複合逆。
[xn]F(x)=[xn−1]nexpC(x)nxnxn=[xn−1]nexpnC(x)
Code
題意:對於k=1...n,求在樹上選k個點的所有方案中,在這k個點中某兩個點的最短路徑上的點數。
發現對於選k個點,答案是一個連通塊,所以邊數=點數−1,所以我們計算總邊數最後加上(kn)即可。
對於一條邊(a,b),它在這個連通塊內即代表這k個點不在同一邊,假設一邊的大小爲sz,則它在這個連通塊內的方案數爲(kn)−(ksz)−(kn−sz)
將組合數拆開k!×(ksz)=(sz−k)!sz!
做一下差卷積即可將(ksz)貢獻到每個k。
Code
0~9種有k種可用數字,求前n/2個數字和與後n/2個數字和相等的方案數
對一個最高次數爲9的多項式求它的105次冪即可。
可以直接做1e6的NTT然後把每個點值快速冪後再NTT回來即可。
也可以通過g=fk,g′=kfk−1f′得到g′f=kgf′
ngnf0=∑i=19kifign−i−∑i=19(n−i)fign−i,f0=0可以通過平移多項式解決。
從而O(81n)得到g=fk。