题意: 给定 n , k n,k n,k,问 ∑ i = 1 n k m o d i \sum_{i=1}^{n}k\bmod i ∑i=1nkmodi,其中 1 ≤ n , k ≤ 1 0 9 1\leq n,k\leq 10^9 1≤n,k≤109
题解:
由:
k
m
o
d
i
=
k
−
⌊
k
i
⌋
×
i
k \bmod i = k - \lfloor \frac{k}{i} \rfloor \times i
kmodi=k−⌊ik⌋×i
得:
∑
i
=
1
n
k
m
o
d
i
=
n
×
k
−
∑
i
=
1
n
⌊
k
i
⌋
×
i
\sum_{i=1}^{n}k\bmod i = n\times k - \sum_{i=1}^n \lfloor \frac{k}{i} \rfloor\times i
∑i=1nkmodi=n×k−∑i=1n⌊ik⌋×i
可以知道一定有一些数
i
i
i的
⌊
k
i
⌋
\lfloor \frac{k}{i} \rfloor
⌊ik⌋相同,这里采用分块思想:
同一块数的
⌊
k
i
⌋
\lfloor \frac{k}{i} \rfloor
⌊ik⌋相同,长度为
m
i
n
(
n
,
k
/
(
k
/
i
)
)
−
i
+
1
min(n, k / (k / i)) - i + 1
min(n,k/(k/i))−i+1,这里的
i
i
i是一个块的左端点,
m
i
n
(
n
,
k
/
(
k
/
i
)
)
min(n, k / (k / i))
min(n,k/(k/i))是一个块的右端点。
这里考虑
k
k
k和
n
n
n大小关系
- 当 k ≤ n k\leq n k≤n时,自然是 k k k的所有值大于 0 0 0分块全部算上,所以当某个分块为 0 0 0时,直接设右边为 n n n即可,下一步就可以结束计算了。
- 当 k > n k>n k>n时, k k k的分块某些部分不能被算上,所以每次枚举右端点时,要取 m i n ( n , r ) min(n,r) min(n,r),保证取的分块不会大于 n n n。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
struct Node{
int x, y;
};
inline ll read() {
ll x = 0, f = 1;
char ch = getchar();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar(); }
while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
void solve() {
ll n = read();
ll k = read();
ll res = n * k;
for(ll l = 1, r; l <= n; l = r + 1) {
r = k / l ? min(n, k / (k / l)) : n;
res -= (k / l) * (r - l + 1) * (l + r) / 2;
}
printf("%lld\n", res);
}
int main()
{
int T = 1;
//scanf("%d", &T);
for(int i = 1; i <= T; ++i){
solve();
}
return 0;
}