Codeforces Round #701 C. Floor and Mod 数学推导
传送门: https://codeforces.com/contest/1485/problem/C
题意
给 一 个 x 和 y , 求 ⌊ a b ⌋ = a m o d b 成 立 的 个 数 。 给一个x和y,求\left \lfloor \frac{a}{b}\right \rfloor =a\;mod\;b成立的个数。 给一个x和y,求⌊ba⌋=amodb成立的个数。
1 ≤ a ≤ x 1 ≤ b ≤ y 1\leq a \leq x\;\;\;1\leq b \leq y 1≤a≤x1≤b≤y
思路
显 然 这 题 是 围 绕 ⌊ a b ⌋ = a m o d b . 显然这题是围绕\left \lfloor \frac{a}{b}\right \rfloor =a\;mod\;b. 显然这题是围绕⌊ba⌋=amodb.
没 有 限 制 的 话 , 会 有 b − 1 个 ( 0 不 存 在 ) 。 没有限制的话,会有\red{b-1}个(0不存在)。 没有限制的话,会有b−1个(0不存在)。
我 们 可 以 手 推 出 3 2 , 4 3 都 可 以 , 并 且 8 3 也 可 以 。 我们可以手推出\frac{3}{2},\frac{4}{3}都可以,并且\frac{8}{3}也可以。 我们可以手推出23,34都可以,并且38也可以。
所 以 b + 1 b = 1 , 2 ( b + 1 ) b = 2 等 等 。 所以\frac{b+1}{b}=1,\frac{2(b+1)}{b}=2等等。 所以bb+1=1,b2(b+1)=2等等。
所 以 我 们 得 出 来 k ( b + 1 ) b = k = a m o d b 。 k ( b + 1 ) ≤ a 所以我们得出来\frac{k(b+1)}{b}=k=a\;mod\;b。\red{k(b+1)\leq a} 所以我们得出来bk(b+1)=k=amodb。k(b+1)≤a
枚 举 b , 但 是 题 目 是 有 限 制 条 件 的 , 取 m i n 就 行 。 枚举b,但是题目是有限制条件的,取min就行。 枚举b,但是题目是有限制条件的,取min就行。
∑ i = 2 b m i n ( i − 1 , a i + 1 ) \sum_{i=2}^bmin(i-1,\frac{a}{i+1}) i=2∑bmin(i−1,i+1a)
首 先 要 算 一 下 中 间 值 i − 1 = a i + 1 , i = a + 1 , 最 后 得 : 首先要算一下中间值i-1=\frac{a}{i+1},i=\sqrt{a+1},最后得: 首先要算一下中间值i−1=i+1a,i=a+1,最后得:
∑ i = 2 a + 1 i − 1 + ∑ i = a + 1 + 1 b a i + 1 \sum_{i=2}^{\sqrt{a+1}}i-1+\sum_{i=\sqrt{a+1}+1}^b\frac{a}{i+1} i=2∑a+1i−1+i=a+1+1∑bi+1a
前 半 部 分 就 等 差 数 列 求 和 , 后 半 部 分 整 除 分 块 即 可 。 前半部分就等差数列求和,后半部分整除分块即可。 前半部分就等差数列求和,后半部分整除分块即可。
Code(62MS)
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
void solve() {
int _; cin >> _;
while(_--) {
ll a, b; cin >> a >> b;
ll ans = 0;
ll t = sqrt(a + 1);
if(t > b) {
t = b;
ans += t * (t - 1) / 2;
}
else {
ans += t * (t - 1) / 2;
for (ll l = t + 1, r; l <= min(a, b); l = r + 1) {
if (a / (l + 1) == 0) break;
else r = min(b, min(a, a / (a / (l + 1)) - 1));
ans += (r - l + 1) * (a / (l + 1));
}
}
cout << ans << endl;
}
}
signed main() {
solve();
}