洛谷2261:余数求和

洛谷2261:余数求和

题意描述

  • \(\sum_{i=1}^nk\ mod\ i\)

数据范围

  • \(n,k\leq 10^9\)

思路

  • 我们知道\(a\%b = a - \lfloor\frac{a}{b}\rfloor*b\)

  • 那么我们上式就可以改写为\(\sum_{i=1}^nk-\lfloor\frac{k}{i}\rfloor*i=n*k-\sum_{i=1}^ni*\lfloor\frac{k}{i}\rfloor\)
  • 那问题就转化成了求\(\sum_{i=1}^ni*\lfloor\frac{k}{i}\rfloor\)
  • 打个表看看。

  • \(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}\rfloor\)是一样的。
  • 所以可以用分块的思想来做。
  • 枚举块的左边界\(l\),右边界\(r=\lfloor \frac{k}{\lfloor \frac{k}{i}\rfloor}\rfloor\)
  • 这样的块大概有\(\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\n", ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zxytxdy/p/12164435.html
今日推荐