整除分块

\(f(n) = \sum\limits^{n}_{i=1}{\lfloor\frac{n}{i}\rfloor}\) ,给定 \(n, n \in [1, 10^9] \cap \mathbb{Z}\) ,求 \(f(n)\)

算法分析

\(n = 20\) 时,有

\(i\) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
\(\lfloor\frac{n}{i}\rfloor\) 20 10 6 5 4 3 2 2 2 2 1 1 1 1 1 1 1 1 1 1

可以看出有连续一块都相同的结果。

事实上有不超过 \(2\sqrt n\) 这样的块个。

\(l\) 为分块左边界,\(r\) 为分块右边界则 \(r = \lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor\), \(l \leq i \leq r\)。为了方便计算可以取 \(i = l\)

整除分块相关证明

代码

将不同的块的数字乘其对应的值,最后相加。一共有 \(O(2 \sqrt n)\) 个块,求对应的值是 \(O(1)\) 的,所以总时间复杂度是 \(O(\sqrt n)\)

int f(int n) {
    int res = 0;
    for(int l = 1, r; l <= n; l = r + 1)
    {
        r = n / (n / l);
        /* n / l 是当前块对应的值 */
        /* r - l + 1 是当前块的长度 */
        res += n / l * (r - l + 1);
    }
    return res;
}

若要求 \(g(n, m) =\sum\limits^n_{i=1}{\lfloor\frac{m}{i}\rfloor}\) ,需要限制围为 \(n\)

int h(int n, int m) {
    int res = 0;
    for(int l = 1, r; l <= n; l = r + 1)
    {
        if(m / l) // m / l 有可能为 0
			r = ::std::min(n, m / (m / l));
		else
			r = n;
        res += m / l * (r - l + 1);
    }
    return res;
}

例题

#1 - 洛谷 P1403 [AHOI2005] 约数研究

洛谷 P1403 [AHOI2005] 约数研究

给定 \(n, n \leq 10^9\) ,求 \(\sum\limits^n_{i=1}F(i)\) ,其中 \(F(x)\) 表示 \(x\) 的正因子个数

解法:

对于一个数 \(d\) ,可以成为 \(\lfloor\frac{n}{d}\rfloor\) 个数的因子,靠虑 \(1 \sim n\) 的每一个数 \(d\) ,则答案为 \(\sum\limits^n_{d=1}{\lfloor\frac{n}{d}\rfloor}\) ,即 \(f(n)\)


#2 - 洛谷 P2424 约数和

洛谷 P2424 约数和

给定 \(X, Y, X < Y \leq 2 \times 10^9\) ,求 \(\sum\limits^Y_{i=X}{\sum\limits_{j|i}{j}}\),即求 \(X \sim Y\) 每个数的正因子之和。

解法:

计算 \(1 \sim Y\)\(1 \sim X - 1\) 每个数的正因子之和,做差即可。

对于一个数 \(d\) ,可以成为 \(\lfloor\frac{n}{d}\rfloor\) 个数的因子,且贡献都为 \(d\),靠虑 \(1 \sim n\) 的每一个数 \(d\) ,则答案为 \(\sum\limits^n_{d=1}{\lfloor\frac{n}{d}\rfloor \cdot d}\)

对于边界为 \(l, r\) 的块,这个块的贡献是 \(\sum\limits^r_{d=l}{\lfloor\frac{n}{l}\rfloor \cdot d} = \lfloor\frac{n}{l}\rfloor \cdot \sum\limits^r_{d=l}{d} = \lfloor\frac{n}{l}\rfloor \cdot \frac{(r - l + 1)(r - l)}{2}\)

ll calc(ll x) {
    ll res = 0;
    for(ll l = 1, r; l <= x; l = r + 1)
    {
        r = x / (x / l);
        res += x / l * (r - l + 1) * (l + r) / 2;
    }
    return res;
}

#3 - 洛谷 P2261 [CQOI2007] 余数求和

P2261 [CQOI2007] 余数求和

给出正整数 \(n\)\(k\)\(n,k \leq 10^9\),计算 \(G(n, k) = \sum\limits_{i = 1}^n{k \bmod i}\)

解法:

\(k \bmod i = k - \lfloor\frac{k}{i}\rfloor \cdot i\)

答案为 \(\sum\limits_{i = 1}^n{(k - \lfloor\frac{k}{i}\rfloor \cdot i)} = nk - \sum\limits_{i = 1}^n{\lfloor\frac{k}{i}\rfloor \cdot i}\) ,这样就和上一个题差不多了,但是要注意边界是 \(n\)


#4 - CF1485 C. Floor and Mod

C. Floor and Mod

\(a \in [1, x] \cap \mathbb{Z}, y \in [1, y] \cap \mathbb{Z}\)\(\lfloor\frac{a}{b}\rfloor = a \bmod b\)\((a,b)\) 个数。

解法:

\[\begin{align} \lfloor\frac{a}{b}\rfloor &= a \bmod b \\ \lfloor\frac{a}{b}\rfloor &= a - \lfloor\frac{a}{b}\rfloor \cdot b \\ (b + 1)\lfloor\frac{a}{b}\rfloor &= a \\ \lfloor\frac{a}{b}\rfloor &= \frac{a}{b + 1} \end{align} \]

\((1)\) 式和 \((4)\) 式可得 \(\frac{a}{b + 1} < b \Rightarrow a < b^2 + b \Rightarrow a \leq b^2 + b - 1\),由 \((3)\) 式可得 \((b + 1) | a\),综上满足条件的 \(a\)\(\lfloor\frac{b^2 + b - 1}{b + 1}\rfloor\) 个,且要 \(a \leq y\),则答案为

\[\begin{aligned} &\sum\limits^y_{b=1}{\lfloor\frac{\min(x, b^2 + b - 1)}{b + 1}}\rfloor \\ &=\sum\limits^{p-1}_{b=1}{\lfloor\frac{b^2 + b - 1}{b + 1}\rfloor + \sum\limits^y_{b=p}{\lfloor\frac{x}{b + 1}\rfloor}} \\ &=\sum\limits^{p-1}_{b=1}{\lfloor\frac{b^2 + b - 1}{b + 1}\rfloor + \sum\limits^{y+1}_{b=p+1}{\lfloor\frac{x}{b}}\rfloor} \\ \end{aligned} \]

其中 \(p\) 满足 \((p - 1)^2 + (p - 1) - 1 \leq x < p^2 + p - 1\)

\(p\) 与加号左边的式子直接枚举即可,因为 \(p = O(\sqrt n)\) 。加号右边整除分块,即 \(g(y + 1, x) - g(p, x)\)


#5 - 洛谷 P3935 Calculating

P3935 Calculating

\(x\) 分解质因数结果为 \(x=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n}\),令\(F(x)=(k_1+1)(k_2+1)\cdots (k_n+1)\),求 \(\sum\limits_{i=l}^rF(i)\)\(998\,244\,353\) 取模的结果。
\(l \leq r \le 1.6 \times 10^{14}\)

解法:

根据 算数基本定理的推论 可知 \(F(x)\) 就是 \(x\) 的正因子个数,求法和例题1一样,则答案为 \(f(r) - f(l - 1)\),注意取模。

#6 - ABC F - Small Products

F - Small Products

\(f_{i,j}\)\(1 \sim i\) 个数中,第 \(i\) 个数为 \(j\) 的合法方案数,则有

\[f_{i,j} = \sum\limits^{\lfloor\frac{n}{j}\rfloor}_{k} f_{i,k} \]

可以发现,多 \(f_{i,j}\) 的值是相同的。重新设计状态 \(f_{i,j}\)\(1 \sim i\) 个数中,第 \(i\) 个在第 \(j\) 块的合法方案数,即可。

posted @ 2024-06-27 21:33  kuailedetongnian  阅读(51)  评论(0)    收藏  举报