單位根反演
知識精要
單位根反演用於計算一個數列中所有 \(k\) 的倍數的和。
具體方法是,我們構造一個多項式,其係數為數列。for(i = 0 -> n - 1)
,將 \(\omega_k^i\) 代入我們構造的多項式,值的和即為答案。
看起來複雜度更差,但是“構造多項式”可能會有一種能更快計算的“封閉形式”(比如二項式定理),能顯著優化複雜度。
證明需要兩個式子:
\[[k|n] = \frac{1}{k} \sum_{i=0}^{k-1}w_k^{in} \]
(顯然)
一看就是等比數列求和,直接套用公式推一推就出來了。
\[\sum_{i=0}^n [k|i]a_i = \frac{1}{k}\sum_{j=0}^{k-1}f(w_k^j) \]
給一個簡單的推導:
\[\sum_{i=0}^n[k|i]a_i \]
\[=\sum_{i=0}^n\sum_{j=0}^{k-1}1/k * w_k^{ij}a_i \]
\[=\frac{1}{k} \sum_{j=0}^{k-1}\sum_{i=0}^na_iw_k^{ji} \]
\[=\frac{1}{k}\sum_{j=0}^{k-1}f(w_k^j) \]
技能展示
#6485. LJJ 學二項式定理
輸入以下變數的值:$ n, s , a_0 , a_1 , a_2 , a_3$,求以下式子的值:
\[\left[ \sum_{i=0}^n \left( {n\choose i} \cdot s^{i} \cdot a_{i\bmod 4} \right) \right] \bmod 998244353 \]
將每個 \(a_i\) 分開考慮。對於每個 \(a_i\),我們要算的是:
\[\sum_{i=0}^n( {n\choose i} s^i)[i \bmod 4 = ...] \]
對於 \(a_0\) 比較好算,直接二項式定理搞上去即可。主要是算 \(a_{1,2,3}\)。
根據生成函式的基本運算,\(f(x)/x\) 能夠達到係數“左移”一位的效果,據此可以計算 \(a_{1,2,3}\)。
程式碼:
ll g[4] = {1, 911660635, 998244352, 86583718}; inline ll calc(ll x) { return quickpow(s * x % P + 1, n); } inline void work() { read(n), read(s); for (register int i = 0; i < 4; ++i) read(a[i]), a[i] %= P; n %= (P - 1); s %= P; ll ans = 0; for (register int i = 0; i < 4; ++i) { ll res = 0; for (register int j = 0; j < 4; ++j) { res += calc(g[j]) * inv(quickpow(g[j], i)) % P; } ans += a[i] * res % P; } ans = (ans % P + P) % P; ans = ans * inv(4) % P; printf("%lld\n", ans); }
P5293 [HNOI2019]白兔之舞
還不會...