(旧存档) 牛客多校第七场-H题
H 数论
思路
留意到每个对 $(n, k)$ 中,$k$ 是独立的,故把每个 $k$ 分开分析。
刚开始我没有留意到 $n$ 一定是 $n \mod k \equiv 0$ 或 $n \mod k \equiv 1$ 的,后面才观察到。
但其实这个性质很容易观察: 1、根据性质1、2,所有 $1 \le n \le N,n \mod k \equiv 1$ 的数 $n$, $(n, k)$ 是合法的 2、根据性质3,所有 $1 \le n \le N,n \mod k \equiv 0$ 的数 $n$, $(n, k)$ 是合法的
因此,当$ k\neq 1,$ $1 \le i \le n $ 时,$(i, k)$ 中合法的对有 $\lfloor \frac{n}{k} \rfloor + \lfloor \frac{n-1}{k} \rfloor + 1$ 个 特别的,当 $k = 1$ 时,有 $n$ 个合法对。
因此 $f(n, k) = n + \sum \limits_{i=2}^{k}(\lfloor \frac{n}{k} \rfloor + \lfloor \frac{n-1}{k} \rfloor + 1)$,使用简单的数论分块即可 $O(\sqrt{k})$ 解决问题。
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MOD = 1e9 + 7;
ll solve(ll n, ll k) {
ll ans = n % MOD;
for (ll l = 2, r; l <= k; l = r + 1) {
ll r1 = k, r2 = k;
if (n / l) r1 = n / (n / l);
if ((n - 1) / l) r2 = (n - 1) / ((n - 1) / l);
r = min(k, min(r1, r2));
ans = (ans + (r - l + 1) % MOD * (n / l + (n - 1) / l + 1)) % MOD;
}
return ans;
}
int main() {
ll n, k;
scanf("%lld%lld", &n, &k);
printf("%lld\n", solve(n, k));
return 0;
}