1. 程式人生 > >卷積 & 杜教篩

卷積 & 杜教篩

最大 證明 整體 事情 關於 等於 枚舉 並且 log

卷積

卷積定義:

  如果有數論函數\(f, g\), 那麽它們卷積的第\(n\)項為\((f * g) (n)\),設這個卷出來的新函數為h,那麽有
  \[h(n) = \sum_{k | n} f(k) g(n / k) = \sum_{ij = n}f(i) g(j)\]
  

一些性質:

  1,積性函數的卷積還是積性函數
  證明: 現有\(f, g\)為積性函數,且\(gcd(p, q) == 1\),求證\(h(p) \cdot h(q) = h(qp).\)
  \[h(p) \cdot h(q) = \sum_{ab = p}f(a) g(b) \cdot \sum_{cd = q}f(c) g(d)\]


  \[= \sum_{a} f(a) g(\frac{p}{a}) \sum_{c} f(c) g(\frac{q}{c})\]
  \[= \sum_{a} \sum_{c} f(a) f(c) g(\frac{p}{a}) g(\frac{q}{c})\]
  \[= \sum_{a} \sum_{c} f(ac) g(\frac{pq}{ac})\]
  因為\(ac \cdot \frac{pq}{ac} = pq\),所以
  \[\sum_{a} \sum_{c} f(ac)g(\frac{pq}{ac}) = \sum_{ac | pq} f(ac)g(\frac{pq}{ac})\]

  \[= \sum_{x|pq}f(x)g(\frac{pq}{x}) = h(pq)\]
  

常見狄利克雷卷積:

\(id = \phi * 1\)
\(d = 1 * 1\)
\(\sigma = id * 1\)
\(e = 1 * \mu\)
\(\phi = id * \mu\)
  

有趣的事情:

  1,FFT(多項式乘法)就是在求卷積。
    可以把\(f,g\)分別看做兩個多項式,\(f(i)\)表示\(x^i\)的系數,\(g(i)\)同理。
    那麽卷出來的\(h(i)\)就等於兩式相乘後\(x^{i}\)的系數,因為卷積定義裏面\(h(k)\)就要加上滿足\(ij = k\)

\(f(i) g(j)\).

杜教篩

目的:在低於線性的時間內求積性函數前綴和

算法:

  設\(S(n) = \sum_{i = 1}^{n}f_{i}\).
  設有一個積性函數\(g(i)\).則:
  \[\sum_{i = 1}^{n}(g * f)(i) = \sum_{i = 1}^{n} \sum_{d | i} g(d)f(\frac{i}{d})\]
  因為當\(d | i\)時會統計到\(g(d)f(\frac{i}{d})\),因此直接枚舉\(d\)\(i = \frac{i}{d}\),\(i\)的最大值為\(\frac{n}{d}\),因為要滿足\(i \cdot d \le n\).所以:
  \[原式= \sum_{d = 1}^{n}g(d) \sum_{i = 1}^{\frac{n}{d}}f(i) = \sum_{d = 1}^{n}g(d)S(\frac{n}{d})\]
  所以:
  \[\sum_{i = 1}^{n}(g * f)(i) = \sum_{d = 1}^{n}g(d)S(\frac{n}{d})\]
  
  因為我們有:
  \[g(1)S(n) = \sum_{i = 1}^{n}g(i)S(\frac{n}{i}) - \sum_{i = 2}^{n}g(i)S(\frac{n}{i})\]
  帶入上式得:
  \[g(1)S(n) = \sum_{i = 1}^{n}(g * f)(i) - \sum_{i = 2}^{n}g(i)S(\frac{n}{i})\]
  因此我們只需要找到一個合適的\(g\),帶入上式,使得\(\sum_{i = 1}^{n}(g * f)(i)\)可以快速計算,那麽就只需要對\(\sum_{i = 2}^{n}g(i)S(\frac{n}{i})\)進行求解就可以得到\(S(n)\),而這個式子中的\(S(\frac{n}{i})\)是可以整數分塊求的。
  於是就可以做到\(O(n^{\frac{3}{4}})\)求解了。
  同時為了降低復雜度,可以先預處理一部分\(S\)值。通過證明可得:設我們當前預處理了前\(k\)個S,那麽當\(k\)取到\(n^{\frac{2}{3}}\)時可以使得整體復雜度降為\(n^{\frac{2}{3}}\).(後面部分記憶化求解)
  
  關於記憶化:
  1,可以使用map/hash解決。
  2,或者觀察到對於同一個\(S(n)\),我們所有要求的\(S\)值都是形如\(S(\frac{n}{x})\)的,並且我們知道\(\lfloor{ \frac{\lfloor{\frac{n}{x}}\rfloor}{y} }\rfloor = \lfloor {\frac{n}{xy}} \rfloor\),因此對於同一個\(n\),我們求的所有\(S(k)\)都可以表示為\(S(\frac{n}{x})\),因此設\(now = \frac{n}{x}\)。那麽:
    1,對於\(now <= n^{\frac{2}{3}}\),我們已經預處理出來了。
    2,對於\(now > n^{\frac{2}{3}}\),因為\(now > n^{\frac{2}{3}}\),所以\(x = \frac{n}{now} <= n ^ {\frac{1}{3}}\),因此我們可以令\(sum[x] = S(\frac{n}{x})\)。即若我們有\(S(now)\) 其中$now > n ^ {\frac{2}{3}} $,那麽我們可以把這個值存入 \(sum[\frac{n}{now}]\).
    註意:但這樣的話,雖然減少一個log,但若有多個不同n值,則每次處理一個新的n值時就需要清空S數組。
    因為雖然對於同一個n值,我們要求的所有S的下標都可以表示為 \(\frac{n}{x}\),但不是任意一個數都可以被表示為 \(\frac{n}{x}\) 的,
    如果這個時候的另一個\(n\)恰好不能被表示,那麽答案就會出錯

卷積 & 杜教篩