zoukankan      html  css  js  c++  java
  • 浅谈高维前缀和

    我们知道一维前缀和是可以这么求的:

    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)]; //做前缀和
    
  • 相关阅读:
    Lua 学习之基础篇七<Lua Module,Package介绍>
    Lua 学习之基础篇六<Lua IO 库>
    Lua 学习之基础篇五<Lua OS 库>
    Lua 学习之基础篇四<Lua table(表)>
    Lua 学习之基础篇三<Lua 字符串操作>
    时空穿梭
    【集训队作业】line
    动态几何问题
    博弈论与概率统计
    wombats
  • 原文地址:https://www.cnblogs.com/withoutpower/p/10497061.html
Copyright © 2011-2022 走看看