测试地址:余数之和
做法:本题需要用到数论分块。
我们发现题目要求的就是:
∑ni=1(k−⌊ki⌋i)
∑
i
=
1
n
(
k
−
⌊
k
i
⌋
i
)
我们知道
⌊ki⌋
⌊
k
i
⌋
只有不超过
2k−−√
2
k
种取值。简单证明一下,当
1≤i≤k−−√
1
≤
i
≤
k
时,
⌊ki⌋
⌊
k
i
⌋
显然最多只有
k−−√
k
种取值,而当
i>k−−√
i
>
k
时,
1≤⌊ki⌋<k−−√
1
≤
⌊
k
i
⌋
<
k
,也显然最多有
k−−√
k
种取值,所以加起来最多有
2k−−√
2
k
种取值。
因为
⌊ki⌋
⌊
k
i
⌋
只有不超过
2k−−√
2
k
种取值,而函数
f(i)=i
f
(
i
)
=
i
的前缀和又十分好求,所以可以把上式分成
2k−−√
2
k
段来计算,每段可以
O(1)
O
(
1
)
算出,这就是数论分块,时间复杂度为
O(k−−√)
O
(
k
)
。
(什么?我以前有写过数论分块?不存在的)
以下是本人代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k;
int main()
{
scanf("%lld%lld",&n,&k);
ll ans=n*k;
for(ll i=min(k,n);i>=1;i=k/(k/i+1))
{
ll l=k/(k/i+1)+1,r=i;
ans-=(k/i)*(r*(r+1)/2-l*(l-1)/2);
}
printf("%lld",ans);
return 0;
}