题目大意:给出正整数
n
n
n,
k
k
k,请计算
G
(
n
,
k
)
=
∑
i
=
1
n
k
m
o
d
i
G(n,k)=\sum_{i=1}^n\ k\ mod\ i
G(n,k)=∑i=1n k mod i
思路:一道整除分块的入门题
整除分块的基本形式为:
∑
i
=
1
n
⌊
n
i
⌋
\sum_{i=1}^n\lfloor \frac{n}{i}\rfloor
∑i=1n⌊in⌋
对于任意一个
i
(
i
≤
n
)
i(i\le n)
i(i≤n),我们要找到一个最大的
j
(
i
≤
j
≤
n
)
j(i\le j\le n)
j(i≤j≤n),使得
⌊
n
i
⌋
=
⌊
n
j
⌋
\lfloor\frac{n}{i}\rfloor=\lfloor\frac{n}{j}\rfloor
⌊in⌋=⌊jn⌋,那么此时
j
=
⌊
n
⌊
n
i
⌋
⌋
j=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor
j=⌊⌊in⌋n⌋
显然 i ≤ j ≤ n i\le j\le n i≤j≤n(证明从略),设 k = ⌊ n i ⌋ k=\lfloor\frac{n}{i}\rfloor k=⌊in⌋,当 ⌊ n j ⌋ = k \lfloor\frac{n}{j}\rfloor=k ⌊jn⌋=k, j m a x = ⌊ n k ⌋ j_{max}=\lfloor\frac{n}{k}\rfloor jmax=⌊kn⌋(证明从略)
那么对于每次以 [ i , j ] [i,j] [i,j]为一块,分块求和即可
Code:
for(ll l=1,r;l<=n;l=r+1){
r=n/(n/l);
ans+=(r-l+1)*(n/l);
}
对于本题来说, ∑ i = 1 n k m o d i = ∑ i = 1 n k − i ∗ ⌊ k i ⌋ = n ∗ k − ∑ i = 1 n i ∗ ⌊ k i ⌋ \sum_{i=1}^n\ k\ mod\ i=\sum_{i=1}^n\ k-i*\lfloor\frac{k}{i}\rfloor=n*k-\sum_{i=1}^n\ i*\lfloor\frac{k}{i}\rfloor ∑i=1n k mod i=∑i=1n k−i∗⌊ik⌋=n∗k−∑i=1n i∗⌊ik⌋
对于 ∑ i = 1 n i ∗ ⌊ k i ⌋ \sum_{i=1}^n\ i*\lfloor\frac{k}{i}\rfloor ∑i=1n i∗⌊ik⌋,我们把每块 [ l , r ] [l,r] [l,r]对应的 ∑ i = l r i ∗ ⌊ k i ⌋ \sum_{i=l}^r\ i*\lfloor\frac{k}{i}\rfloor ∑i=lr i∗⌊ik⌋中,令 T = ∑ i = l r ⌊ k i ⌋ T=\sum_{i=l}^r\lfloor\frac{k}{i}\rfloor T=∑i=lr⌊ik⌋, ∑ i = l r i ∗ ⌊ k i ⌋ = T ∗ ∑ i = l r i = T ∗ l + r 2 \sum_{i=l}^r\ i*\lfloor\frac{k}{i}\rfloor=T*\sum_{i=l}^r\ i=T*\frac{l+r}{2} ∑i=lr i∗⌊ik⌋=T∗∑i=lr i=T∗2l+r
复杂度 O ( n ) O(\sqrt n) O(n)
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=2e3+10,mod=1e9+7;
typedef long long ll;
ll n,k;
int main(){
cin>>n>>k;
ll ans=n*k;
for(ll l=1,r;l<=n;l=r+1){
if(k/l!=0) r=min(n,k/(k/l));
else r=n;
ans-=(l+r)*(k/l)*(r-l+1)/2;
}
cout<<ans<<endl;
return 0;
}