洛谷2261:余数求和
题意描述
- 求(sum_{i=1}^nk mod i)。
数据范围
- (n,kleq 10^9)。
思路
-
我们知道(a\%b = a - lfloorfrac{a}{b} floor*b)。
-
那么我们上式就可以改写为(sum_{i=1}^nk-lfloorfrac{k}{i} floor*i=n*k-sum_{i=1}^ni*lfloorfrac{k}{i} floor)。
-
那问题就转化成了求(sum_{i=1}^ni*lfloorfrac{k}{i} floor)。
-
打个表看看。
-
取(k=5,n=8)好了。
i=1 | i=2 | i=3 | i=4 | i=5 | i=6 | i=7 | i=8 |
---|---|---|---|---|---|---|---|
5 | 2 | 1 | 1 | 1 | 0 | 0 | 0 |
- 我们可以发现其实有好多(lfloor frac{n}{i} floor)是一样的。
- 所以可以用分块的思想来做。
- 枚举块的左边界(l),右边界(r=lfloor frac{k}{lfloor frac{k}{i} floor} floor)。
- 这样的块大概有(sqrt{n})个。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, k, ans;
int main()
{
scanf("%lld%lld", &n, &k);
ans += n * k;
for(ll l = 1, r; l <= n; l = r + 1)
{
if(k / l != 0) r = min(k/(k/l), n);
else r = n; //当左端点大于k的时候,直接跳过
ans -= (r-l+1) * (l+r)/2 * (k/l);
} puts("");
printf("%lld
", ans);
return 0;
}