首先一道例题
题意
给定 n , k < = 1 e 9 n,k<=1e9 n,k<=1e9,求 ∑ i = 1 n k % i \sum_{i=1}^{n}k\%i i=1∑nk%i
直接算肯定是要T的,我们想办法对 k % i k\%i k%i进行变形
k % i = k − i ∗ ⌊ k i ⌋ k\%i=k-i*\lfloor \frac{k}{i}\rfloor k%i=k−i∗⌊ik⌋
∑ i = 1 n k % i = ∑ i = 1 n k − i ∗ ⌊ k i ⌋ = n k − ∑ i = 1 n i ∗ ⌊ k i ⌋ \sum_{i=1}^{n}k\%i=\sum_{i=1}^{n}k-i*\lfloor \frac{k}{i}\rfloor=nk-\sum_{i=1}^{n}i*\lfloor \frac{k}{i}\rfloor i=1∑nk%i=i=1∑nk−i∗⌊ik⌋=nk−i=1∑ni∗⌊ik⌋
那么对这个有限的 ⌊ k i ⌋ \lfloor \frac{k}{i}\rfloor ⌊ik⌋分块即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXN 150005
#define LL long long
#define Mod 1000000007
#define Int register long long
using namespace std;
inline void read(LL &x)
{
x = 0;
LL f = 1;
char s = getchar();
while (s < '0' || s > '9')
{
if (s == '-')
f = -1;
s = getchar();
}
while (s >= '0' && s <= '9')
{
x = (x << 3) + (x << 1) + (s ^ 48);
s = getchar();
}
x *= f;
}
inline LL Min(LL x,LL y)
{
return x < y ? x : y;
}
int main()
{
LL n, k;
read( n ); read( k );
LL Ans = n * k;
for (Int l = 1, r; l <= n; l = r + 1)
{
LL t = k / l;
if (! t)
r = n;
else r = Min(n, k / t);
Ans -= (l + r) * (r - l + 1) / 2 * t;
}
printf("%lld", Ans);
return 0;
}