那来点模板题。求的是模数和,看起来和上面的整除分块没有什么关系,但是: \[ \sum_{i=1}^n k\mod i = \sum_{i=1}^n k - \lfloor\frac{k}i\rfloor i = nk - \sum_{i=1}^n \lfloor\frac{k}i\rfloor i \] 这样处理之后,右边的部分仍然不是我们熟悉的整出分块形式,所以还需要进一步处理;
我们已经知道了 \(\sum_{i=1}^n \lfloor\frac{k}i\rfloor\) 在一定范围内具有相同的值,那么在块内我们令 \(T_j = \lfloor\frac{k}j\rfloor\),那么就可以进行如下形式的化简: \[ \sum_{i=1}^n \lfloor\frac{k}i\rfloor i = \sum_{i=1}^n T_i\cdot i = \sum_j\sum_{i=L}^R T_i\cdot \sum_{i=L}^R i \] 这样,在每一个分块内,左边是整除分块,右边是一个公差为 1 的等差数列;块内只需要一个定值和一个很好求的和,就可以分块来做了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
signedmain(){ #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif auto n = read(), k = read(); auto ans = n * k; for (llong l = 1, r; l <= n; l = r + 1) { if (k / l) r = min(k / (k / l), n); else r = n; ans -= (r - l + 1) * (l + r) / 2 * (k / l); } cout << ans << endl; return0; }
lll fast_pow(lll a, lll b = mod - 2){ lll ret = 1; while (b) { if (b & 1) (ret *= a) %= mod; (a *= a) %= mod, b >>= 1; } return ret %= mod; }
llong euler_phi(llong n){ auto ans = n; for (llong i = 2; i * i <= n; ++i) if (!(n % i)) { ans = ans / i * (i - 1); while (!(n % i)) n /= i; } if (n > 1) ans = ans / n * (n - 1); return ans; }
signedmain(){ #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif lll n = read(), m = read(), k = min(n, m); auto nm = n * m % mod, n2m = nm * n % mod; auto n2m2 = nm * nm % mod, nm2 = nm * m % mod; constauto calc = [](lll n, lll k) { lll ret = 0; minimize(n, k); for (lll l = 1, r; l <= n; l = r + 1) { if (k / l) r = min(k / (k / l), n); else r = n; auto sum = (r - l + 1) * (l + r) / 2 % mod; (ret += sum * (k / l) % mod) %= mod; } return ret %= mod; }; constauto sum_mod = [&calc](lll n, lll k) { return (n * k % mod - calc(n, k) + mod) % mod; }; constauto phi_mod = euler_phi(mod) - 1; constauto inv6 = fast_pow(6, phi_mod); constauto sum_i2 = [inv6](lll n) { return n * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod; }; constauto lp = sum_mod(n, n) * sum_mod(m, m) % mod; auto knm = k * nm % mod, rp = knm; for (lll l = 1, r; l <= k; l = r + 1) { if (n / l && m / l) r = min({n / (n / l), m / (m / l), k}); else r = k; auto si2 = (sum_i2(r) - sum_i2(l - 1) + mod) % mod; auto inm = (n / l) * (m / l) % mod; (rp += inm * si2 % mod) %= mod; } auto ckn = calc(k, n), ckm = calc(k, m); auto tmp = (m * ckn % mod + n * ckm % mod) % mod; rp = (rp + mod - tmp) % mod; cout << llong((lp + mod - rp) % mod) << endl; return0; }
constexpr lll fast_pow(lll a, lll b = mod - 2){ lll ret = 1; while (b) { if (b & 1) (ret *= a) %= mod; (a *= a) %= mod, b >>= 1; } return ret %= mod; }
lll sum_i2(lll n){ return n * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod; }
lll sum_i(lll n){ return (n + 1) * n % mod * inv2 % mod; }
lll xi2(lll l, lll n, lll k){ lll ret = 0; minimize(n, k); for (lll r; l <= n; l = r + 1) { if (k / l) r = min(k / (k / l), n); else r = n; auto val = (k / l) * (k / l) % mod; (ret += (r - l + 1) * val % mod) %= mod; } return ret; }
lll xi(lll l, lll n, lll k){ lll ret = 0; minimize(n, k); for (lll r; l <= n; l = r + 1) { if (k / l) r = min(k / (k / l), n); else r = n; (ret += (r - l + 1) * (k / l) % mod) %= mod; } return ret; }
lll sum_ix(lll n, lll x){ auto m = n % x + 1, d = n / x; if (!d) return0; lll ret = x * sum_i(d - 1) % mod; (ret += m * d % mod) %= mod; return ret; }
lll sum_ix2(lll n, lll x){ auto m = n % x + 1, d = n / x; if (!d) return0; lll ret = x * sum_i2(d - 1) % mod; auto d2 = d * d % mod; (ret += m * d2 % mod) %= mod; return ret; }