前缀和的本质理解
向量法
我们都知道 AB=OB−OA,那么把它放在数轴上,类比可知:
如果 pre[i]=∑i=1na[i],则:
i=l∑ra[i]=pre[r]−pre[l−1]
积分法
如果 F′(x)=f(x),则 ∫abf(x)=F(b)−F(a),也是同一个道理。
如何判断两数列相等
如果 F=G,F′(x)=f(x),G′(x)=g(x),则 f=g,类比可知:
如果 pre[i]=pre′[i],则 a[i]=a′[i]。
前缀和的好处
区间求值
可以 O(1) 求出 ∑i=lra[i]。
降低维度
对于 ∑i=lra[i],其有两个维度 l,r,数量级是 n2,而化为 pre[r],pre[l−1] 处理,维度减少了一,数量级是 n。
知道 ∑i=lra[i],就能得出 pre[r],pre[l−1] 之间的关系。
前缀和的数学计算(可跳过)
类比积分,我们需要引入有限微积分和无限微积分的概念。
无限微积分(微分算子 D)
Df(x)=h→0limhf(x+h)−f(x)
有限微积分(差分算子 Δ)
Δf(x)=1f(x+1)−f(x)=f(x+1)−f(x)
两者对比
众所周知:
Dxm=mxm−1
而对于有限微积分,有没有类似的结论?
事实上,引入 xm,称为下降阶乘幂,其定义是:
xm=x(x−1)⋯(x−m+1)
则,Δ(xm)=x(x−1)⋯(x−m+1)−(x−1)⋯(x−m)=mxm−1,结论与上面类似。
运用到积分
设 ∑abg(x)δx=f(b)−f(a),其中 Δf(x)=g(x),则由定义我们推出 ∑abg(x)δx=∑a≤x<bg(x)。
注:这里的 δ 是 Δ 的小写,类比 d 是 D 的小写。
可以试着代入 g(x)=xm,则 f(x)=m+1xm+1,则:
0≤k<n∑km=f(n)−f(0)=m+1nm+1
于是我们可以试着用待定系数法(或者多项式除法)来求解 ∑0≤k<nka,其中 a 是正整数。
函数乘积的差分
已知 Δu(x),Δv(x),u(x),v(x),求 Δ(u(x)v(x))。
由定义,我们有:
Δ(u(x)v(x))=u(x+1)v(x+1)−u(x)v(x)=(Δu(x)+u(x))(Δv(x)+v(x))−u(x)v(x)=u(x)Δv(x)+v(x)Δu(x)+Δu(x)Δv(x)
或者写成不对称的形式:
u(x)Δv(x)+v(x+1)Δu(x)
分部积分
回顾无限微积分下分部积分的法则:
∫udv=uv−∫vdu
我们令 E 为移位算子,具体地,Ev(x)=v(x+1),则有类似的法则:
∑uΔv=uv−∑EvΔu
如果我们想要求 ∑k2k,则:
=∑x2xδx(u=x,Δv=2x⇒Δu=1,v=2x)x2x−∑E2xδx=x2x−2x+1+C
则 ∑k=0nk2k=∑0n+1x2xδx=x2x−2x+1∣0n+1=(n−1)2n+1+2。
其他方法
拉格朗日法
由上面的积分法,虽然不能精确地得出一些前缀和式的通项,但是可以由归纳法知道式子的次数是有限的。
这样我们就可以取点 1,2,⋯,n,进行插值。
生成函数法
如果我们要求数列 {an} 的前缀和,可以构造生成函数:
F(x)=i=1∑naixi
与
G(x)=1+x+x2+⋯=1−x1
相乘。如果要求 k 维前缀和,则计算 F(x)×(1−x1)k,求 ln,exp 即可。
如果求差分,也是类似的道理。
本质上是 {an} 与 {1,1,⋯} 的卷积。
不同维度上的前缀和、差分
通常我们需要结合容斥原理计算。
二维前缀和
设数组 a[n][m],记 s[x][y]=∑i=1x∑j=1ya[i][j],递推求 s[x][y]:
s[x][y]=s[x−1][y]+s[x][y−1]−s[x−1][y−1]+a[x][y]
求 (x1,y1),(x2,y2) 所构成的矩形的数之和:
sum=s[x2][y2]−s[x1−1][y2]−s[x2][y1−1]+s[x1−1][y1−1]
高维前缀和
https://gaisaiyuno.github.io/archives/cb88f9ef.html
树上差分
点差分
du→du+1dv→dv+1dlca→dlca−1dfa(lca)→dfa(lca)−1
可以将每一次操作理解为从当前节点到根节点都进行了同样的改变,点差分的意义就不难理解。
边差分
du→du+1dv→dv+1dlca→dlca−2
狄利克雷前缀和
已知 {a} 求:
bk=i∣k∑ai
首先,我们向狄利克雷卷积的定义寻求帮助:
(f∗g)(n)=xy=n∑f(x)g(y)
令 f(i)=ai,g(i)=1,即 g=one。莫比乌斯反演即可。
或者,我们可以从高维前缀和的角度理解,分析标准素因数分解式,这里 po 一篇洛谷的题解:
1 2 3
| for(Rint i = 1;i <= tot;i ++) for(Rint j = 1;pri[i] * j <= n;j ++) a[pri[i] * j] += a[j];
|
前缀和处理的元素
具有加、减的性质,具体来说,具有 ∘+,∘− 两种运算,满足 (a∘+b)∘−b=a。
比如说 a∘+b=(a+b)(modm),a∘−b=(a−b)(modm),又如 ∘+=∘−=⊕。