算法模板

a.位运算

1.快速幂

ll qmi(int m, int k, int p)
{
    ll res = 1 % p, t = m;
    while (k)
    {
        if (k&1) res = res * t % p;
        t = t * t % p;
        k >>= 1;
    }
    return res;
}

b.前缀和与差分

1.一维前缀和

a数组:1 2 3 4 5 6

b数组:1 3 6 10 15 21

\(b[i] = a[i] + b[i - 1] (下标从1开始)\)

求1,2的和,就可以转换为\(b[2] - b[1 - 1]\),也就是求\(l-r\),为\(b[r] - b[l - 1]\);


2.二维前缀和

通过一维前缀和我们自然也可以推出二维前缀和

\(s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1]\)为从(x1,y1)到(x2,y2)二维数组内的元素之和

例如
图片

图片s(x2,y2)为从(0,0)到此的总和,s(x1,y1)为从(0,0)到此的和。我们在如果要算(x1,y1)到(x2,y2)的之间元素的总和,我们需要把s(x2,y2)减去s(x2,y1)以及s(x1,y2)

然后还要加上s(x1,y1),因为该区域被减了二次。

所以可以得出\(s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1]\)公式,

\(s[x2][y1 - 1]\)可以类比一维的前缀和,我们是减去下标前面的下标,之后也是相类似。


3.一维差分

1 2 3 4 5 6
1 1 1 1 1 1

差分处理:b[i] = a[i] - a[i - 1]

场景:

我们将下标1到下标3的数每个数加上一

使用朴素做法,那么我们就要变量区域的每一个值加上一,\(0(n)\)的时间复杂度。

使用差分数组,\(b[3 + 1] --,b[1]++\),只需要0(1)的时间复杂度。

还原数组:b[i] += b[i - 1]

4.二维差分

使用上面二维前缀和的例子
将(x1,y1)到(x2,y2)区域的数组同时减或者加。

\[s[x2 + 1][y2 + 1] += c\newline s[x2 + 1][y1] -= c\newline s[x1][y2 + 1] -= c\newline s[x1][y1] += c \]

类似一维差分,是数组的下一个下标进行。

posted @ 2022-05-21 14:57  knowei  阅读(25)  评论(0编辑  收藏  举报