数论分块,约数研究

文章借用: 浅谈数论分块 - 洛谷专栏 (luogu.com)

求 $\sum_{i=1}^n \lfloor\frac{n}{i}\rfloor$,其中 $n$ 为常数。

为了方便我们的研究,我使用绘图软件画出了 $f(x) =\frac{7}{x}(1\leq x\leq 7)$ 的图像,也就是一种反比例函数的图像。

 因为求的值是向下取整的,显然函数 $f(x)$ 在 $[1,7]$ 区间内是单调递减的,我们不妨把 $\lfloor \frac n i\rfloor$ 取值相同的段取出来

 图像被分割为了 $7$ 个大块,但取值范围包含整数的只有 $4$ 个,那么如果我们可以把这些包含整数的块取出来,一次性得出一个块的答案,把整块对答案的贡献加上即可。

如果要实现整块一起统计,我们需要求出每一块的块头 $l$ 和块尾 $r$,则:

$$\sum_{i=1}^n \lfloor \frac n i \rfloor = \sum _{(l,r)} (r-l+1) \lfloor \frac n l \rfloor$$

给出一个结论: 对于整数 $i$,其所在块的右端点为 $\lfloor\frac{n}{\lfloor \frac n i \rfloor}\rfloor$,在此给出两种证明方式:

1. 代数法

首先我们要证明 $\lfloor\frac{n}{\lfloor \frac n i \rfloor}\rfloor$ 与 $i$ 在同一块,也就是:$$\lfloor\frac{n}{\lfloor\frac{n}{\lfloor \frac n i \rfloor}\rfloor}\rfloor= \lfloor\frac{n}{i}\rfloor$$

易证:

$$ \lfloor x\rfloor \leq x$$

$$x \le y\to \lfloor x\rfloor \le \lfloor y\rfloor$$

$$x \ge y\to \lfloor x\rfloor \ge \lfloor y\rfloor$$

则:

$$\lfloor\frac{n}{\lfloor\frac{n}{\lfloor \frac n i \rfloor}\rfloor}\rfloor \ge \lfloor\frac{n}{\frac{n}{\lfloor \frac n i \rfloor}}\rfloor=\lfloor\frac{n}{i}\rfloor$$

$$\lfloor\frac{n}{\lfloor\frac{n}{\lfloor \frac n i \rfloor}\rfloor}\rfloor \le \lfloor\frac{n}{\lfloor\frac{n}{ \frac n i }\rfloor}\rfloor=\lfloor\frac{n}{i}\rfloor$$

所以:

$$\lfloor\frac{n}{\lfloor\frac{n}{\lfloor \frac n i \rfloor}\rfloor}\rfloor= \lfloor\frac{n}{i}\rfloor$$

我们还要证明:

$$i \le \lfloor\frac{n}{\lfloor \frac n i \rfloor}\rfloor$$

也就是 $\lfloor\frac{n}{\lfloor \frac n i \rfloor}\rfloor$ 是这个块内最大的,即为块的右端点,这个很好证明:

$$\lfloor\frac{n}{\lfloor \frac n i \rfloor}\rfloor\ge \lfloor\frac{n}{ \frac n i }\rfloor=i$$

这样我们就以代数方式证明了结论,如果看不懂还有几何的。

2. 几何法

$\frac{n}{\lfloor \frac n i \rfloor}$ 的意义即为直线 $y=\lfloor \frac n i \rfloor$ 与直线 $y=\frac n x$ 的交点的横坐标,取整后就是这个交点左侧第一个整数横坐标,如图:

 $l_1$ 为直线 $y = \lfloor \frac n i \rfloor $,$l_2$ 为直线 $y=\lfloor \frac n i \rfloor +1$,我们不妨设 $l1$ 与直线 $y=\frac n x$ 的交点为 $P$,$l_2$ 与直线 $y=\frac n x$ 的交点为 $Q$,则:

\forall x_Q < x \leq x_p, \left\lfloor \frac{x}{n} \right\rfloor = \left\lfloor \frac{i}{n} \right\rfloor

那么 $x_{P}$ 也就是 $\frac{n}{\lfloor \frac n i \rfloor}$ 左侧的第一个整点 $\lfloor \frac{n}{\lfloor \frac n i \rfloor}\rfloor$ 即为这些点里的最大整数点。

证毕.

复杂度证明: 

当 $x \in [1, \lfloor\sqrt n\rfloor]$ 这个区间,最多有 $\lfloor\sqrt n\rfloor$ 种取值。

当 $x \in (\lfloor\sqrt n\rfloor,n]$ 这个区间,$\lfloor\frac n x\rfloor$ 显然只能取到 $[1, \lfloor\sqrt n\rfloor)$这个区间,最多有 $\lfloor\sqrt n\rfloor$ 种取值。

则至多有 $2\lfloor\sqrt n\rfloor$ 种取值,复杂度为 $O(\sqrt n)$。

代码:

 for(int l=1,r;l<=x;l=r+1) r=x/(x/l),res=(res+((r-l+1)*(x/l)));

 

题目: 

P3935 Calculating - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

一道比较模板的题,显然题目中的 $f(x)$ 就是 $x$ 的约数个数,设 $g(x)=\sum_{i = 1} ^x f(i)$, 那么有一个常见套路:

$$\sum_{i=l}^r f(i)=g(r) - g(l-1)$$

$$g(x)=\sum_{i = 1} ^x f(i)=\sum_{i = 1} ^x \sum_{k = 1} ^x [i\mid k]=\sum_{i=1}^x\lfloor\frac x i\rfloor$$

大致的意思就是枚举一下 $i\in[1,x]$,看 $i$ 在 $[1,x]$ 中是多少个数的约数,然后加起来就好了,这里有个结论:

$$\sum_{i=1}^n[x \mid i] =\lfloor\frac n x\rfloor $$

注: 至于这道题为什么是求约数的个数,可以这样理解,任何一个数都可以被几个质数相乘得到,因为一个数可以分成几个数,如果这些数还可以分,就继续分,到最后一定会分不了,这些分不了的数就是质数,所以说一个数可以被多个质数相乘得到

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=998244353;
int cacl(int x){
    int res=0;
    for(int l=1,r;l<=x;l=r+1)
        r=x/(x/l),res=(res+((r-l+1)*(x/l))%mod)%mod;
    return res;
}
signed main(){
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int l,r; cin>>l>>r;
    cout<<(cacl(r)-cacl(l-1)+mod)%mod;
}

0因数平方和 - 蓝桥云课 (lanqiao.cn)

推一下式子会发现, $g[x]$就是 从 1 到 x 的所有数乘 $x/i$ 向下取整,考虑分块即可,运用平方和公式可以实现任何两个数之间的平方和 

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=1e9+7;
int cacl(int x){
    return x*(__int128)(x+1)*(2*x+1)/6%mod;
}
signed main(){
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int n,res=0; cin>>n;
    for(int i=1,j;i<=n;i=j+1)
        j=n/(n/i),res=(res+((cacl(j)-cacl(i-1))*(n/i))%mod)%mod;
    cout<<(res+mod)%mod;
}

 

posted @ 2024-03-26 13:00  o-Sakurajimamai-o  阅读(15)  评论(0编辑  收藏  举报
-- --