高维前缀和
前缀和
迪利克雷前缀和:给定 \(f(1),f(2),\dots f(n)\),求 \(g(d)=\sum\limits_{x\mid d}f(x)\),\(d\in[1,n]\)。
问题中的 \(g\) 就是就是 \(f\) 的迪利克雷前缀和,直接求是 \(O(n\ln n)\) 的,但可以做到 \(O(n\log\log{n})\)。
设 \(x=\prod p_i^{\alpha_i}\),\(y=\prod p_i^{\beta_i}\),那么 \(x\) 贡献到 \(y\) 当且仅当 \(\forall i,~\alpha_i\le \beta_i\)。因此这就是一个质因数分解之后,指数的高位前缀和问题,先筛出 \(\le n\) 的所有质数,然后按位依次前缀和即可(每个质数是一”位“)
for(int i = 1; i <= cnt; ++i) // cnt是质数个数
for(int j = 1; j * prime[i] <= n; ++j)
f[j * prime[i]] += f[j]; // j * prime[i] 在第 i 位上的指数比 j 多 1
类似地,我们还有迪利克雷后缀和:\(g(d)=\sum\limits_{d\mid x}f(x)\)。
注意区别在于 \(d\mid x\) 还是 \(x\mid d\)。计算方法也是类似的。
for(int i = 1; i <= cnt; ++i) // cnt是质数个数
for(int j = n / prime[i]; j >= 1; --j)
f[j] += f[j * prime[i]]; // j 在第 i 位上的指数比 j * prime[i] 少 1
差分
前缀差分:给定 \(g(1),g(2),\dots g(n)\),已知 \(g(d)=\sum\limits_{x\mid d}f(x)\),求 \(f(x)\),\(x\in [1, n]\)。
站在高维前缀和/差分的角度,我们只需要将前缀和的那一层循环反向,然后加号变减号即可。
for(int i = 1; i <= cnt; ++i)
for(int j = n / prime[i]; j >= 1; --j)
f[j * prime[i]] -= f[j];
后缀差分:给定 \(g(1),g(2),\dots g(n)\),已知 \(g(d)=\sum\limits_{d\mid x}f(x)\),求 \(f(x)\),\(x\in [1, n]\)。
for(int i = 1; i <= cnt; ++i)
for(int j = 1; j * prime[i] <= n; ++j)
f[j] -= f[j * prime[i]];
例题
ABC361F x=a^b
给定一个正整数 \(n\),求 \(1\) ~ \(n\) 中有多少个数能被写成 \(a^b~(b\ge 2)\) 的形式。
\(n\le 10^{18}\)
这里只写莫比乌斯反演/后缀差分的做法
首先 \(a=1\) 时显然有且仅有 \(x=1\) 符合题意,接下来默认 \(a\ge 2\)
注意到 \(b\) 不会超过 \(59\),所以可以枚举 \(b\)。
对于一个 \(b\),有 \(\lfloor \sqrt[b]{n} \rfloor -1\) 个 \(a\) 符合题意。
但是我们不能把 \(\lfloor \sqrt[b]{n} \rfloor -1\) 之和当作答案,因为 \(a_1^{b_1}=a_2^{b_2}\) 的情况会导致算重。
思考一下会发现,同一个数 \(x\) 可能会有多种拆分方式,比如
此时我们希望规定一种方式,使得拆分是唯一的,就不会存在重复了。
所以可以让 \(a\) “最简”,也就是 \(a\) 不能表示为 \(p^q\) 的形式,这时我们可以说 \(x=a^b\) 是“幂次只能是 \(b\) 的数”
那么之前,我们计算的\(\lfloor \sqrt[b]{n} \rfloor -1\) 个 \(a^b\) 就是“幂次只能是 \(kb\) 的数\(~(k\in\Z)\)”。这是因为没有限定 \(a\) 最简,所以 \(a\) 可以继续拆分。
于是我们设 \(f(b)\) 表示 “幂次只能是 \(b\) 的数的个数”,\(g(b)\) 表示“幂次只能是 \(kb\) 的数的个数”,则有下面的关系式:
我们的目的是求出 \(f\),这种式子有两种处理方式
一:莫比乌斯反演
结论是
可以线性筛出 \(\mu(1\) ~ \(n)\),然后 \(O(n\ln{n})\) 求 \(f\)
答案是 \(1+\sum\limits_{i=2}^nf(n)\)
二:高维前缀和
我们可以把一个数进行质因数分解,如 \(n=p_1^{c_1}\cdot p_2^{c_2}\cdot\dots\cdot p_k^{c_k}\)
这样我们就可以认为 \(n\) 是一个有 \(k\) 个维度的向量 \((c_1,c_2,\dots,c_k)\)
对于最初的式子
这里 \(b\mid x\) 在多维视角下是什么意思呢?
不难发现,\(b\mid x\) 表示 \(x\) 在每一维度下的数值都大于 \(c\)
那么这个式子所反映的关系就是:\(g\) 是 \(f\) 在多维视角下的“后缀和”
所以 \(f\) 就是 \(g\) 的后缀差分