知识点 - 整除分块
1.约数个数
令 τ ( n ) \tau(n) τ(n)为n的约数个数,求其前缀和。
解析
若n的质因数分解为
n
=
p
1
e
1
⋅
p
2
e
2
⋯
p
k
e
k
n=p_1^{e_1} \cdot p_2^{e_2} \cdots p_k^{e_k}
n=p1e1⋅p2e2⋯pkek,则
τ
(
n
)
=
(
e
1
+
1
)
⋅
(
e
2
+
1
)
⋯
(
e
k
+
1
)
\tau(n) = (e_1 + 1) \cdot (e_2 + 1) \cdots (e_k + 1)
τ(n)=(e1+1)⋅(e2+1)⋯(ek+1)
不过求这个前缀和时不需要此公式。
我们有
∑
i
=
1
n
τ
(
i
)
=
∑
i
=
1
n
∑
j
=
1
n
[
j
∣
i
]
=
∑
i
=
1
n
⌊
n
i
⌋
\sum_{i=1}^{n}\tau(i)=\sum_{i=1}^{n}{\sum_{j=1}^{n}{[j|i]}}=\sum_{i=1}^{n}\lfloor\frac {n}{i}\rfloor
i=1∑nτ(i)=i=1∑nj=1∑n[j∣i]=i=1∑n⌊in⌋
对于
y
1
=
⌊
n
x
⌋
y
2
=
n
x
y_1=\lfloor\frac{n}{x}\rfloor\\\ \\ y_2=\frac{n}{x}
y1=⌊xn⌋ y2=xn
n
=
12
n=12
n=12时作图如下:
当
i
≤
n
i≤\sqrt n
i≤n时,
⌊
n
i
⌋
\lfloor\frac{n}{i}\rfloor
⌊in⌋显然只有
O
(
n
)
O(\sqrt n)
O(n)个取值;当
i
>
n
i>\sqrt n
i>n时,
⌊
n
i
⌋
<
n
\lfloor\frac{n}{i}\rfloor<\sqrt n
⌊in⌋<n显然也只有
O
(
n
)
O(\sqrt n)
O(n)个取值;
对于固定
⌊
n
i
⌋
\lfloor\frac{n}{i}\rfloor
⌊in⌋,
i
i
i的取值是一段连续的区间,这段区间是
[
⌊
n
⌊
n
i
⌋
+
1
⌋
+
1
,
⌊
n
⌊
n
i
⌋
⌋
]
[\left\lfloor\frac{n}{\left\lfloor\frac{n}{i}\right\rfloor+1}\right\rfloor+1,\left\lfloor\frac{n}{\left\lfloor\frac{n}{i}\right\rfloor}\right\rfloor]
[⌊⌊in⌋+1n⌋+1,⌊⌊in⌋n⌋]
几何上可以理解为先找到对应的红线,即求出i点的值
v
=
⌊
n
i
⌋
v=\lfloor\frac{n}{i}\rfloor
v=⌊in⌋;然后求出红线的终点,即右区间
r
=
⌊
n
v
⌋
r=\lfloor\frac{n}{v}\rfloor
r=⌊vn⌋,以及它的起点
l
=
⌊
n
v
+
1
⌋
l=\lfloor\frac{n}{v+1}\rfloor
l=⌊v+1n⌋
将 ⌊ n ⌊ n i ⌋ ⌋ \left\lfloor\frac{n}{\left\lfloor\frac{n}{i}\right\rfloor}\right\rfloor ⌊⌊in⌋n⌋作为分界线,所以有如下代码:
int ans = 0;
for (int l = 1, r; l <= n; l = r + 1){
r = n / (n / l);
ans += (r - l + 1)*(n / l);
}
右区间的代数证明,?戳这里。
2.约数和
令 σ ( i ) \sigma(i) σ(i)为n的约数和,求前缀和。
oeis A024916
解析
类似上面,有:
σ
(
n
)
=
p
1
e
1
+
1
−
1
p
1
−
1
⋅
p
2
e
2
+
1
−
1
p
2
−
1
⋯
p
k
e
k
+
1
−
1
p
k
−
1
\sigma(n) = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1} \cdot \frac{p_2^{e_2 + 1} - 1}{p_2 - 1} \cdots \frac{p_k^{e_k + 1} - 1}{p_k - 1}
σ(n)=p1−1p1e1+1−1⋅p2−1p2e2+1−1⋯pk−1pkek+1−1
同上也没用。因为我们可以直接写出:
∑
i
=
1
n
σ
(
i
)
=
∑
i
=
1
n
∑
j
=
1
n
[
j
∣
i
]
⋅
j
=
∑
i
=
1
n
i
⋅
∑
j
=
1
n
[
i
∣
j
]
=
∑
i
=
1
n
i
⋅
⌊
n
i
⌋
=
∑
i
=
1
n
⌊
n
i
⌋
⋅
(
⌊
n
i
⌋
+
1
)
2
\sum_{i=1}^{n}{\sigma(i)}=\sum_{i=1}^{n}{\sum_{j=1}^{n}{[j|i]\cdot j}}=\sum_{i=1}^{n}{i\cdot\sum_{j=1}^{n}{[i|j]}}=\sum_{i=1}^{n}{i\cdot\lfloor\frac{n}{i}\rfloor}=\sum_{i=1}^{n}{\frac{\lfloor\frac{n}{i}\rfloor\cdot (\lfloor\frac{n}{i}\rfloor+1)}{2}}
i=1∑nσ(i)=i=1∑nj=1∑n[j∣i]⋅j=i=1∑ni⋅j=1∑n[i∣j]=i=1∑ni⋅⌊in⌋=i=1∑n2⌊in⌋⋅(⌊in⌋+1)
最后的等式
∑
i
=
1
n
i
⋅
⌊
n
i
⌋
=
∑
i
=
1
n
⌊
n
i
⌋
⋅
(
⌊
n
i
⌋
+
1
)
2
\sum_{i=1}^{n}{i\cdot\lfloor\frac{n}{i}\rfloor}=\sum_{i=1}^{n}{\frac{\lfloor\frac{n}{i}\rfloor\cdot (\lfloor\frac{n}{i}\rfloor+1)}{2}}
i=1∑ni⋅⌊in⌋=i=1∑n2⌊in⌋⋅(⌊in⌋+1)
可以看成对每个
⌊
n
i
⌋
\lfloor\frac{n}{i}\rfloor
⌊in⌋固定的块,将
⌊
n
i
⌋
\lfloor\frac{n}{i}\rfloor
⌊in⌋提出来,然后对
i
∈
[
⌊
n
⌊
n
i
⌋
+
1
⌋
+
1
,
⌊
n
⌊
n
i
⌋
⌋
]
i\in[\left\lfloor\frac{n}{\left\lfloor\frac{n}{i}\right\rfloor+1}\right\rfloor+1,\left\lfloor\frac{n}{\left\lfloor\frac{n}{i}\right\rfloor}\right\rfloor]
i∈[⌊⌊in⌋+1n⌋+1,⌊⌊in⌋n⌋]等差数列求和。
int f(int n) {
int ans = 0;
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
ans += (r - l + 1)*(n / l)*(n / l + 1) / 2;
}
return ans;
}
signed main()
{
int l, r;
while (cin >> l>>r) {
cout << f(r) - f(l - 1) << endl;
}
return 0;
}