题目大意:
给出数 x , y x,y x,y,求 ∑ i = 1 y x \sum_{i=1}^{y}x ∑i=1yx m o d mod mod i i i。
1 ≤ x , y ≤ 1 e 9 1≤x,y≤1e9 1≤x,y≤1e9
分析:
x
x
x
m
o
d
mod
mod
i
=
i=
i=
x
−
⌊
x
i
⌋
∗
i
x-\left \lfloor \frac{x}{i} \right \rfloor*i
x−⌊ix⌋∗i
那么
∑
i
=
1
y
x
\sum_{i=1}^{y}x
∑i=1yx
m
o
d
mod
mod
i
=
i=
i=
∑
i
=
1
y
x
−
⌊
x
i
⌋
∗
i
=
\sum_{i=1}^{y}x-\left \lfloor \frac{x}{i} \right \rfloor*i=
∑i=1yx−⌊ix⌋∗i=
x
y
−
∑
i
=
1
y
⌊
x
i
⌋
∗
i
xy-\sum_{i=1}^{y}\left \lfloor \frac{x}{i} \right \rfloor*i
xy−∑i=1y⌊ix⌋∗i
因为
⌊
x
i
⌋
\left \lfloor \frac{x}{i} \right \rfloor
⌊ix⌋取值至多有
2
x
2 \sqrt{x}
2x
所以
∑
i
=
1
y
⌊
x
i
⌋
∗
i
\sum_{i=1}^{y}\left \lfloor \frac{x}{i} \right \rfloor*i
∑i=1y⌊ix⌋∗i中的
⌊
x
i
⌋
\left \lfloor \frac{x}{i} \right \rfloor
⌊ix⌋必定是相同的一段一段的,
n
\sqrt{n}
n的求一下分界点即可,然后对于后面的乘就是等差数列了。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <algorithm>
#define N 100005
using namespace std;
typedef long long ll;
ll Num[N], A, B, Answer = 0;
int cnt;
ll Get_Sum(ll x, ll y)
{
if (x > y) return 0;
return (x + y) * (y - x + 1) / 2;
}
int main()
{
scanf("%lld %lld", &A, &B);
for (ll i = 1; i * i <= A; i++) Num[++cnt] = A / i;
for (ll i = 2; i <= sqrt(A) + 1; i++)
if (A / i != A / (i - 1)) Num[++cnt] = i - 1;
Num[++cnt] = 0;
sort(Num + 1, Num + cnt + 1);
Answer = (ll)A * B;
for (int i = 1; i < cnt; i++)
if (Num[i + 1] > B) { Answer = Answer - (ll)Get_Sum(Num[i] + 1, B) * (A / B); break; }
else Answer = Answer - (ll)Get_Sum(Num[i] + 1, Num[i + 1]) * (A / Num[i + 1]);
printf("%lld\n", Answer);
return 0;
}