给你一个正整数
n
n
n ,让你求
∑
n
i
=
1
⌊
n
i
⌋
\underset{i=1}{\overset{n}{\sum}}\lfloor\frac{n}{i}\rfloor
i=1∑n⌊in⌋ 其中
1
≤
n
≤
1
0
9
1\le n\le 10^9
1≤n≤109,
⌊
x
⌋
\lfloor x\rfloor
⌊x⌋ 表示
x
x
x 向下取整,
∑
n
i
=
1
f
(
i
)
\underset{i=1}{\overset{n}{\sum}}f(i)
i=1∑nf(i) 表示求
i
=
1
,
2
,
⋯
,
n
i=1,2,\cdots,n
i=1,2,⋯,n时候,
f
(
i
)
f(i)
f(i) 的和。
思路
我们首先考虑,暴力
f
o
r
for
for 循环做的话,时间复杂度为
O
(
n
)
O(n)
O(n),会超时肯定不行。
我们其次考虑打表,看看有什么规律。当
n
=
30
n=30
n=30 时候:
i
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
⌊
n
i
⌋
\lfloor \frac{n}{i}\rfloor
⌊in⌋
30
15
10
7
6
5
4
3
3
3
2
2
2
2
2
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
可以看到,对于某一段
i
i
i ,
⌊
n
i
⌋
\lfloor \frac{n}{i}\rfloor
⌊in⌋ 的值都相同。 我们能不能这样一段一段地枚举,然后分别对每一段计算贡献呢?
如果我们知道了每一段的左端点
L
L
L 和右端点
R
R
R 那么这一段的贡献容易得到:
(
R
−
L
+
1
)
×
⌊
n
L
⌋
(R-L+1)\times\lfloor \frac{n}{L}\rfloor
(R−L+1)×⌊Ln⌋ 并且我们也可以轻松得到下一段的左端点为目前右端点+1
那么最难问题来了:已知左端点
L
L
L ,怎么求这一段的右端点
R
R
R ? 转变成数学语言,就是已知
L
L
L ,求
R
max
R_{\max}
Rmax,使得
⌊
n
L
⌋
=
⌊
n
R
⌋
\lfloor \frac{n}{L}\rfloor=\lfloor \frac{n}{R}\rfloor
⌊Ln⌋=⌊Rn⌋ 我们设
⌊
n
L
⌋
=
k
\lfloor \frac{n}{L}\rfloor=k
⌊Ln⌋=k,即
n
=
L
k
+
p
n=Lk+p
n=Lk+p,
0
≤
p
<
L
0\le p<L
0≤p<L 我们设
R
=
L
+
d
R=L+d
R=L+d,带入得到
⌊
n
L
+
d
⌋
=
k
\lfloor \frac{n}{L+d}\rfloor=k
⌊L+dn⌋=k,即
n
=
(
L
+
d
)
k
+
p
′
n=(L+d)k+p^\prime
n=(L+d)k+p′,
0
≤
p
′
<
L
0\le p^\prime<L
0≤p′<L 下面式子减去上面式子,得到
p
′
=
p
−
d
k
p^\prime=p-dk
p′=p−dk 此时
d
max
=
⌊
p
k
⌋
d_{\max}=\lfloor\frac{p}{k}\rfloor
dmax=⌊kp⌋,带入
R
=
L
+
d
R=L+d
R=L+d 得到
R
=
L
+
⌊
p
k
⌋
=
L
+
⌊
n
%
L
⌊
n
L
⌋
⌋
=
L
+
⌊
n
−
⌊
n
L
⌋
L
⌊
n
L
⌋
⌋
=
⌊
L
+
n
−
⌊
n
L
⌋
L
⌊
n
L
⌋
⌋
=
⌊
⌊
n
L
⌋
L
⌊
n
L
⌋
+
n
−
⌊
n
L
⌋
L
⌊
n
L
⌋
⌋
=
⌊
n
⌊
n
L
⌋
⌋
\begin{aligned} R&=L+\lfloor\frac{p}{k}\rfloor\\ &=L+\lfloor\frac{n\%L}{\lfloor\frac{n}{L}\rfloor}\rfloor\\ &=L+\lfloor\frac{n-\lfloor\frac{n}{L}\rfloor L}{\lfloor\frac{n}{L}\rfloor}\rfloor\\ &=\lfloor L+\frac{n-\lfloor\frac{n}{L}\rfloor L}{\lfloor\frac{n}{L}\rfloor}\rfloor\\ &=\lfloor\frac{\lfloor\frac{n}{L}\rfloor L}{\lfloor\frac{n}{L}\rfloor}+\frac{n-\lfloor\frac{n}{L}\rfloor L}{\lfloor\frac{n}{L}\rfloor}\rfloor\\ &=\lfloor\frac{n}{\lfloor\frac{n}{L}\rfloor}\rfloor \end{aligned}
R=L+⌊kp⌋=L+⌊⌊Ln⌋n%L⌋=L+⌊⌊Ln⌋n−⌊Ln⌋L⌋=⌊L+⌊Ln⌋n−⌊Ln⌋L⌋=⌊⌊Ln⌋⌊Ln⌋L+⌊Ln⌋n−⌊Ln⌋L⌋=⌊⌊Ln⌋n⌋ 我们得到了,对于某一段的
L
L
L ,这时
R
=
⌊
n
⌊
n
L
⌋
⌋
R=\lfloor\frac{n}{\lfloor\frac{n}{L}\rfloor}\rfloor
R=⌊⌊Ln⌋n⌋
最后一个问题:该算法的时间复杂度是多少? 易得,对于一个数
n
n
n ,该数字的正因子的个数是
O
(
2
n
)
O(2\sqrt n)
O(2n) 级别的 故数论分块的时间复杂度为
O
(
n
)
O(\sqrt n)
O(n)
例题
约束研究 | 洛谷 P1403
[AHOI2005]约数研究 求
∑
n
i
=
1
d
(
i
)
\underset{i=1}{\overset{n}{\sum}}d(i)
i=1∑nd(i)
1
≤
n
≤
1
0
6
1\le n\le 10^6
1≤n≤106,其中
d
(
n
)
d(n)
d(n) 表示
n
n
n 的约数个数。
稍微想一下,枚举每一个数的约数的个数很复杂,那我们直接枚举每一个约数,考虑每个约数的贡献次数。 约数范围
1
∼
n
1\sim n
1∼n,对于某一个约数
i
i
i ,共有
⌊
n
i
⌋
\lfloor\frac{n}{i}\rfloor
⌊in⌋ 个数字有该约数。 式子直接转化为
∑
n
i
=
1
⌊
n
i
⌋
\underset{i=1}{\overset{n}{\sum}}\lfloor\frac{n}{i}\rfloor
i=1∑n⌊in⌋ 注意到,我们可以做
n
≤
1
0
14
n\le 10^{14}
n≤1014 的数据范围。
约数和 | 洛谷 P2424 给你正整数
a
、
b
a、b
a、b ,求
∑
b
i
=
a
σ
(
i
)
\underset{i=a}{\overset{b}{\sum}}\sigma(i)
i=a∑bσ(i)
1
≤
a
≤
b
≤
2
×
1
0
9
1\le a\le b\le 2\times10^9
1≤a≤b≤2×109,其中
σ
(
n
)
\sigma(n)
σ(n) 表示
n
n
n 的约数和。
容易想到,答案即为
∑
b
i
=
1
σ
(
i
)
−
∑
a
−
1
i
=
1
σ
(
i
)
\underset{i=1}{\overset{b}{\sum}}\sigma(i)-\underset{i=1}{\overset{a-1}{\sum}}\sigma(i)
i=1∑bσ(i)−i=1∑a−1σ(i) 我们要求
∑
n
i
=
1
σ
(
i
)
\underset{i=1}{\overset{n}{\sum}}\sigma(i)
i=1∑nσ(i),枚举每一个约数,计算答案,式子转化为
∑
n
i
=
1
i
×
⌊
n
i
⌋
\underset{i=1}{\overset{n}{\sum}}i\times \lfloor\frac{n}{i} \rfloor
i=1∑ni×⌊in⌋ 对于同一段,计算贡献为
L
×
(
L
+
1
)
×
⋯
×
R
×
⌊
n
L
⌋
=
⌊
n
L
⌋
×
(
L
+
R
)
×
(
R
−
L
+
1
)
2
L\times(L+1)\times\cdots\times R\times \lfloor\frac{n}{L}\rfloor=\lfloor\frac{n}{L}\rfloor\times\frac{(L+R)\times(R-L+1)}{2}
L×(L+1)×⋯×R×⌊Ln⌋=⌊Ln⌋×2(L+R)×(R−L+1)
/*
_ __ __ _ _
| | \ \ / / | | (_)
| |__ _ _ \ V /__ _ _ __ | | ___ _
| '_ \| | | | \ // _` | '_ \| | / _ \ |
| |_) | |_| | | | (_| | | | | |___| __/ |
|_.__/ \__, | \_/\__,_|_| |_\_____/\___|_|
__/ |
|___/
*/
ll solve(ll n){
ll L =1,R =0;
ll res =0;while(L <= n){
R = n/(n/L);
res += n / L *(L + R)*(R - L +1)/2;
L = R +1;}return res;}intmain(){
ll a,b;cin >> a >> b;
cout <<solve(b)-solve(a-1);return0;}
余数求和 | 洛谷 P2261
余数求和 | 洛谷 P2261 给你正整数
n
、
k
n、k
n、k,求
∑
n
i
=
1
k
%
i
\underset{i=1}{\overset{n}{\sum}}\ k\ \%\ i
i=1∑nk%i
1
≤
n
,
k
≤
1
0
9
1\le n,k\le 10^9
1≤n,k≤109
取模符号?我们化简一下式子
∑
n
i
=
1
k
%
i
=
∑
n
i
=
1
k
−
i
⌊
k
i
⌋
=
n
k
−
∑
n
i
=
1
i
⌊
k
i
⌋
\underset{i=1}{\overset{n}{\sum}}\ k\ \%\ i=\underset{i=1}{\overset{n}{\sum}}k-i\lfloor\frac{k}{i}\rfloor=nk-\underset{i=1}{\overset{n}{\sum}}i\lfloor\frac{k}{i}\rfloor
i=1∑nk%i=i=1∑nk−i⌊ik⌋=nk−i=1∑ni⌊ik⌋ 看到,右半部分类似一个整除分块。不同的是,分子部分为
k
k
k 而不是
n
n
n。 考虑到
∀
x
>
k
,
都
有
⌊
k
x
⌋
=
0
\forall x>k,都有\lfloor\frac{k}{x}\rfloor=0
∀x>k,都有⌊xk⌋=0。 并且我们每次枚举,要保证右端点
R
R
R 不超过
n
n
n 。
求
∑
min
(
n
,
m
)
i
=
1
⌊
n
i
⌋
×
⌊
m
i
⌋
\underset{i=1}{\overset{\min(n,m)}{\sum}}\lfloor\frac{n}{i}\rfloor\times\lfloor\frac{m}{i}\rfloor
i=1∑min(n,m)⌊in⌋×⌊im⌋
思路:类似于一维,只不过二维的块数变为
2
m
+
2
n
2\sqrt m+2\sqrt n
2m+2n块。 每一个小块里面,
⌊
n
i
⌋
×
⌊
m
i
⌋
\lfloor\frac{n}{i}\rfloor\times\lfloor\frac{m}{i}\rfloor
⌊in⌋×⌊im⌋ 的值都相同。 我们对于一个
L
L
L ,最大的
R
R
R 怎么找呢?易得为
min
{
⌊
n
⌊
n
L
⌋
⌋
,
⌊
m
⌊
m
L
⌋
⌋
}
\min\{\lfloor\frac{n}{\lfloor\frac{n}{L}\rfloor}\rfloor,\lfloor\frac{m}{\lfloor\frac{m}{L}\rfloor}\rfloor\}
min{⌊⌊Ln⌋n⌋,⌊⌊Lm⌋m⌋}
求
∑
n
i
=
1
∑
m
j
=
1
(
n
m
o
d
i
)
×
(
m
m
o
d
j
)
,
i
≠
j
\underset{i=1}{\overset{n}{\sum}}\underset{j=1}{\overset{m}{\sum}}(n\bmod i)\times(m\bmod j),i\ne j
i=1∑nj=1∑m(nmodi)×(mmodj),i=j
思路:不要忘记
i
≠
j
i\ne j
i=j 啊! 我们开始推狮子:
I
=
∑
n
i
=
1
∑
m
j
=
1
(
n
−
⌊
n
i
⌋
i
)
×
(
m
−
⌊
m
j
⌋
j
)
−
∑
min
(
n
,
m
)
i
=
1
(
n
−
⌊
n
i
⌋
i
)
×
(
m
−
⌊
m
i
⌋
i
)
=
∑
n
i
=
1
(
n
−
⌊
n
i
⌋
i
)
∑
m
j
=
1
(
m
−
⌊
m
j
⌋
j
)
−
∑
min
(
n
,
m
)
i
=
1
(
n
m
−
n
⌊
m
i
⌋
i
−
m
⌊
n
i
⌋
i
+
⌊
m
i
⌋
⌊
n
i
⌋
i
2
)
=
(
n
2
−
∑
n
i
=
1
⌊
n
i
⌋
i
)
(
m
2
−
∑
m
j
=
1
⌊
m
j
⌋
j
)
−
min
(
n
,
m
)
×
n
m
+
n
∑
min
(
n
,
m
)
i
=
1
⌊
m
i
⌋
i
+
m
∑
min
(
n
,
m
)
i
=
1
⌊
n
i
⌋
i
−
∑
min
(
n
,
m
)
i
=
1
⌊
n
i
⌋
⌊
m
i
⌋
i
2
\begin{aligned} I&=\underset{i=1}{\overset{n}{\sum}}\underset{j=1}{\overset{m}{\sum}}(n-\lfloor\frac{n}{i}\rfloor i)\times(m-\lfloor\frac{m}{j}\rfloor j)-\underset{i=1}{\overset{\min(n,m)}{\sum}}(n-\lfloor\frac{n}{i}\rfloor i)\times(m-\lfloor\frac{m}{i}\rfloor i)\\ &=\underset{i=1}{\overset{n}{\sum}}(n-\lfloor\frac{n}{i}\rfloor i)\underset{j=1}{\overset{m}{\sum}}(m-\lfloor\frac{m}{j}\rfloor j)-\underset{i=1}{\overset{\min(n,m)}{\sum}}(nm-n\lfloor\frac{m}{i}\rfloor i-m\lfloor\frac{n}{i}\rfloor i+\lfloor\frac{m}{i}\rfloor\lfloor\frac{n}{i}\rfloor i^2)\\ &=(n^2-\underset{i=1}{\overset{n}{\sum}}\lfloor\frac{n}{i}\rfloor i)(m^2-\underset{j=1}{\overset{m}{\sum}}\lfloor\frac{m}{j}\rfloor j)-\min(n,m)\times nm+n\underset{i=1}{\overset{\min(n,m)}{\sum}}\lfloor\frac{m}{i}\rfloor i+m\underset{i=1}{\overset{\min(n,m)}{\sum}}\lfloor\frac{n}{i}\rfloor i-\underset{i=1}{\overset{\min(n,m)}{\sum}}\lfloor\frac{n}{i}\rfloor\lfloor\frac{m}{i}\rfloor i^2 \end{aligned}
I=i=1∑nj=1∑m(n−⌊in⌋i)×(m−⌊jm⌋j)−i=1∑min(n,m)(n−⌊in⌋i)×(m−⌊im⌋i)=i=1∑n(n−⌊in⌋i)j=1∑m(m−⌊jm⌋j)−i=1∑min(n,m)(nm−n⌊im⌋i−m⌊in⌋i+⌊im⌋⌊in⌋i2)=(n2−i=1∑n⌊in⌋i)(m2−j=1∑m⌊jm⌋j)−min(n,m)×nm+ni=1∑min(n,m)⌊im⌋i+mi=1∑min(n,m)⌊in⌋i−i=1∑min(n,m)⌊in⌋⌊im⌋i2 好家伙,清华集训的题就是不一样。。。 注意:模数
19940417
=
7
×
2848631
19940417=7\times2848631
19940417=7×2848631不是质数!用拓欧或者欧拉定理求出逆元! 我们使用函数封装一下,即可优雅 地敲出AC代码 时间复杂度:
O
(
max
(
n
,
m
)
)
O(\sqrt{\max(n,m)})
O(max(n,m))
/*
_ __ __ _ _
| | \ \ / / | | (_)
| |__ _ _ \ V /__ _ _ __ | | ___ _
| '_ \| | | | \ // _` | '_ \| | / _ \ |
| |_) | |_| | | | (_| | | | | |___| __/ |
|_.__/ \__, | \_/\__,_|_| |_\_____/\___|_|
__/ |
|___/
*/const ll MOD =19940417;
ll ex_gcd(ll a,ll b,ll& x,ll& y){if(b==0){
x=1;y=0;return a;}
ll ans=ex_gcd(b,a%b,x,y);
ll tmp=x;
x=y;
y=tmp-a/b*y;return ans;}
ll iv(ll a,ll mod)//存在逆元条件:gcd(a,mod)=1{
ll x,y;
ll g=ex_gcd(a,mod,x,y);if(g!=1)return-1;return(x % mod + mod)% mod;}/// 数论分块,项数为 n ,分子为 k
ll solve(ll n,ll k){
ll L =1,R =0;
ll res =0;while(L <=min(n,k)){
R =min(n,k/(k/L));
res =(res + k / L % MOD *(L + R)% MOD *(R - L +1)% MOD *iv(2,MOD)% MOD);
L = R +1;}
res =(res % MOD + MOD)% MOD;return res;}/// 快速算 1^2 + 2^2 + …… + x^2
ll pre(ll x){
ll res = x *(x +1)% MOD *(2* x +1)% MOD *iv(6,MOD)% MOD;return res;}/// 二维数论分块,项数为 n ,一项分子为 a,另一项分子为 b
ll solve2(ll n,ll a,ll b){
ll L =1,R =0;
ll res =0;while(L <= n){
R =min(a/(a/L),b/(b/L));
res =(res +(a / L)*(b / L)% MOD *(pre(R)-pre(L -1)% MOD))% MOD;/// 注意 i^2 快速求和
L = R +1;}
res =(res % MOD + MOD)% MOD;return res;}intmain(){
ll n,m;
cin >> n >> m;
ll ans =(n * n % MOD -solve(n,n))*(m * m % MOD -solve(m,m))% MOD;
ans =(ans -min(n,m)* n % MOD * m % MOD + n *solve(min(n,m),m)% MOD + m *solve(min(n,m),n)% MOD)% MOD;
ans =(ans -solve2(min(n,m),n,m))% MOD;
ans =(ans + MOD)% MOD;
cout << ans;return0;}
⋆
^\star
⋆扩展
⌈
\lceil
⌈数论分块变形
⌋
\rfloor
⌋
求
∑
n
i
=
1
⌈
n
i
⌉
\underset{i=1}{\overset{n}{\sum}}\lceil\frac{n}{i}\rceil
i=1∑n⌈in⌉ 其中
⌈
x
⌉
\lceil x\rceil
⌈x⌉ 表示
x
x
x 向上取整。
思路:有一个转化:对于正整数
a
、
b
a、b
a、b,我们有
⌈
a
b
⌉
=
⌊
a
+
b
−
1
b
⌋
\lceil\frac{a}{b}\rceil=\lfloor\frac{a+b-1}{b}\rfloor
⌈ba⌉=⌊ba+b−1⌋ 。 证明:设
⌈
a
b
⌉
=
⌊
a
+
b
−
1
b
⌋
=
x
\lceil\frac{a}{b}\rceil=\lfloor\frac{a+b-1}{b}\rfloor=x
⌈ba⌉=⌊ba+b−1⌋=x。 因为
⌈
a
b
⌉
=
x
\lceil\frac{a}{b}\rceil=x
⌈ba⌉=x,我们得出
a
b
∈
(
x
−
1
,
x
]
\frac{a}{b}\in(x-1,x]
ba∈(x−1,x] 又因为
b
b
b 是正整数,所以
b
−
1
b
∈
[
0
,
1
)
\frac{b-1}{b}\in[0,1)
bb−1∈[0,1) 所以
a
b
+
b
−
1
b
∈
(
x
−
1
,
x
+
1
)
\frac{a}{b}+\frac{b-1}{b}\in(x-1,x+1)
ba+bb−1∈(x−1,x+1) 所以
⌊
a
+
b
−
1
b
⌋
=
x
\lfloor\frac{a+b-1}{b}\rfloor=x
⌊ba+b−1⌋=x 所以
⌈
a
b
⌉
=
⌊
a
+
b
−
1
b
⌋
□
\lceil\frac{a}{b}\rceil=\lfloor\frac{a+b-1}{b}\rfloor\qquad\Box
⌈ba⌉=⌊ba+b−1⌋□
代替原式子,得到
∑
n
i
=
1
⌈
n
i
⌉
=
∑
n
i
=
1
⌊
n
+
i
−
1
i
⌋
=
∑
n
i
=
1
(
⌊
n
−
1
i
⌋
+
1
)
\underset{i=1}{\overset{n}{\sum}}\lceil\frac{n}{i}\rceil=\underset{i=1}{\overset{n}{\sum}}\lfloor\frac{n+i-1}{i}\rfloor=\underset{i=1}{\overset{n}{\sum}}(\lfloor\frac{n-1}{i}\rfloor+1)
i=1∑n⌈in⌉=i=1∑n⌊in+i−1⌋=i=1∑n(⌊in−1⌋+1) 这个应该不用代码了吧,和上述代码同理请仔细思考哦。