https://www.luogu.org/problemnew/show/P2261
给出正整数n和k,计算G(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数。例如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,k <= 10^9
in:10 5 out:29
数据范围过大,考虑优化,想到a mod b = a - (a / b) * b,(a / b)为向下取整值
则答案求解的即是sigma(k - (k / i) * i) | 1<=i<=n -> n*k - sigma((k / i) * i) | 1<=i<=n
分析(k/i)发现可以将(k/i)相同的值分为一块,用该块的平均值及长度求出整块的值减掉
对一个左端点l,则(k / l)为该区间的值,右端点即为(k / (k / l))。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 50 + 5;
typedef long long ll;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
ll n, k;
cin >> n >> k;
ll 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;
ans -= (k / l) * (r - l + 1) * (l + r) / 2;
}
cout << ans << endl;
}