总览:
解决一类求和问题
∑
i
=
1
n
⌊
n
i
⌋
\sum_{i=1}^{n}{\lfloor \frac {n}{i} \rfloor}
∑i=1n⌊in⌋
发现一段
i
i
i中
⌊
n
i
⌋
\lfloor \frac {n}{i} \rfloor
⌊in⌋的值不变,于是可以分块求和
假设每一块的左右区间是
[
l
,
r
]
[l,r]
[l,r],则知道
l
l
l后,
r
=
n
n
/
l
r=\frac {n}{n/l}
r=n/ln(均为整除)
证明
那么设两个指针
l
,
r
l,r
l,r,每次
l
=
r
+
1
,
r
=
n
n
/
l
l=r+1,r=\frac {n}{n/l}
l=r+1,r=n/ln后再数量乘以值累加即可
模板:
for(int l=1,r=0;l<=n;l=r+1){
if(n/l==0) break;
r=n/(n/l);//如果循环为k,写成min(k/(k/l),n);
ans+=(n/l)*(r-l+1)/2;
}
时间复杂度:
O
(
n
)
O(\sqrt n)
O(n)
所以时间复杂度为
O
(
n
)
O(\sqrt n)
O(n)
T1 P2261 [CQOI2007]余数求和
[CQOI2007]余数求和
题目描述
给出正整数
n
n
n 和
k
k
k 计算
G
(
n
,
k
)
=
k
m
o
d
1
+
k
m
o
d
2
+
k
m
o
d
3
+
⋯
+
k
m
o
d
n
G(n, k)=k\ \bmod\ 1 + k\ \bmod\ 2 + k\ \bmod\ 3 + \cdots + k\ \bmod\ n
G(n,k)=k mod 1+k mod 2+k mod 3+⋯+k mod n 的值 其中
k
m
o
d
i
k\ \bmod\ i
k mod i 表示
k
k
k 除以
i
i
i 的余数。
例如 G ( 10 , 5 ) = 5 m o d 1 + 5 m o d 2 + 5 m o d 3 + 5 m o d 4 + 5 m o d 5 ⋯ + 5 m o d 10 = 0 + 1 + 2 + 1 + 0 + 5 + 5 + 5 + 5 + 5 = 29 G(10, 5)=5\ \bmod\ 1 + 5\ \bmod\ 2 + 5\ \bmod\ 3 + 5\ \bmod\ 4 + 5\ \bmod\ 5 \cdots + 5\ \bmod\ 10 =0+1+2+1+0+5+5+5+5+5=29 G(10,5)=5 mod 1+5 mod 2+5 mod 3+5 mod 4+5 mod 5⋯+5 mod 10=0+1+2+1+0+5+5+5+5+5=29
输入格式
两个整数
n
n
n ,
k
k
k
输出格式
答案一行
输入输出样例
输入
10 5
输出
29
说明/提示
100
%
:
n
,
k
≤
1
0
9
100\%: n , k \le 10^9
100%:n,k≤109
思路:
有
a
%
b
=
a
−
a
/
b
×
b
a\%b=a-a/b\times b
a%b=a−a/b×b
则
G
(
n
,
k
)
=
k
×
k
−
⌊
a
b
⌋
×
b
G(n,k)=k\times k-\lfloor \frac{a}{b} \rfloor \times b
G(n,k)=k×k−⌊ba⌋×b
数论分块,对于一个块
[
l
,
r
]
[l,r]
[l,r]:
⌊
a
b
⌋
\lfloor \frac{a}{b} \rfloor
⌊ba⌋为定值,
∑
b
\sum b
∑b为块中数的和,为
(
l
+
r
)
×
(
r
−
l
+
1
)
2
\frac {(l+r)\times (r-l+1)}{2}
2(l+r)×(r−l+1)
代码:
#include<bits/stdc++.h>
using namespace std;
#define in Read()
#define int long long
inline int in{
int s=0,f=1;char x;
for(x=getchar();x<'0'||x>'9';x=getchar()) if(x=='-') f=-1;
for( ;x>='0'&&x<='9';x=getchar()) s=(s<<1)+(s<<3)+(x&15);
return f==1?s:-s;
}
int n,k;
int ans;
signed main(){
n=in,k=in;
for(int l=1,r=0;l<=n;l=r+1){
if(k/l==0) break;
r=min(k/(k/l),n);
ans+=(k/l)*(l+r)*(r-l+1)/2;
}
printf("%lld\n",n*k-ans);
return 0;
}