Dirichlet 前綴和的幾種版本


【模板】Dirichlet 前綴和

\[B[i] = \sum_{d|i} A[d] \]

$ n \le 2\times 10^{7} $

看代碼:

for( int i = 1 ; i <= en && pri[i] <= n ; ++ i ) {
        for (int j = 1; j * pri[i] <= n; ++j) {
            B[j * pri[i]] += B[j];
        }
    }

為啥這么做它是對的呢?發現每個數字會被它除以所有質因子轉移到,並且是按照質因子從小到大來的。

所以這個代碼相當於,對所有質因子遞歸求,然后對對所有質因子搞前綴和。

形式和 埃篩 一樣,復雜度也是 $ O(n\log\log n) $

然后考慮這個

\[B[i] = \sum_{i|d} A[d] \]

看代碼:

for( int i = 1 ; i <= en && pri[i] <= n ; ++ i ) {
        for (int j = n / pri[i]; j; --j) {
            B[j] += B[j * pri[i]];
        }
    }

首先,我們發現最主要的區別在於,我們應當從 一個數字本身 轉移到 這個數字除以所有質因子。因為是從大到小轉移的,所以也需要逆序枚舉 $ j $ 。

最后考慮這個:

\[A[i] = \sum_{d|i} B[d] \]

也是已知 $ A $ 求 $ B $

這種情況其實就是第一種情況反過來,我們也可以直接把循環順序和轉移方法給反過來

for( int i = en ; i ; -- i ) {
        for (int j = n / pri[i]; j ; -- j) {
            B[j * pri[i]] -= B[j];
        }
    }

第二種情況也可以反過來,就不贅述了。

例題:CF585E


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM