淺談高維前綴和


我們知道一維前綴和是可以這么求的:

for (int i = 1; i <= n; ++i) a[i] += a[i - 1];

而一維前綴和是可以這么求的:

for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j)
        a[i][j] = a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];

這是基於容斥的做法

當然我們也可以一維一維的去累計:

for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j)
        a[i][j] += a[i][j - 1]; //累計了每一行的前綴和
for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j)
        a[i][j] += a[i - 1][j];//累計了每一列的前綴和

容易看出,當數組的位數變高的時候,如果我們要基於容斥去計算數組前綴和,容斥的項數越來越多,寫起來也更加復雜,而如果我們按照維數去統計,則會有比較好的效果.

比如,給出$a[i]$ ,對於每一個$i$,求出$\sum_{j \& i = j} a[j]$

這道題其實是讓我們求出某個數二進制狀態下的子集和,如果我們對於每一個數去枚舉子集復雜度是$3n$的,其中$n$為二進制位數,但是,如果我們把一個數看成一個$n$維空間,那么題目中要求的其實就是一個$n$維的前綴和,我們仿照上面的形式,一維一維的掃過去求和即可,復雜度$O(n*2n)$.

for (int i = 0; i < n; ++i) //遍歷每一維
    for (int j = 0; j < (1 << n); ++j)
        if ((j >> i) & 1) a[j] += a[j ^ (1 << i)]; //做前綴和


免責聲明!

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



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