「解题报告」ARC127F ±AB

发布时间 2023-03-23 18:53:57作者: APJifengc

首先容易想到 \(m\) 较大时答案为 \(m+1\)。具体的,当 \(m \ge a+b-1\) 时,从任意一个位置出发都可以进行操作,所以答案为 \(m+1\)

\(m \le a + b - 2\) 时,我们发现,对于每一个位置,我们最多只可以进行两种操作。那么也就是说,如果第一步操作确定后,剩下的操作也确定了。具体来说,我们有两种操作序列:

  • \(+a\)\(+a\),能 \(-b\)\(-b\)
  • \(+b\)\(+b\),能 \(-a\)\(-a\)

首先可以分析出两个结论:

  1. 这样操作不会经过重复的数。
    假如出现了重复的数,说明 \(xa + yb = 0\),而由于 \(\gcd(a, b) = 1\),这说明环的大小至少为 \(a+b\),而 \(m \le a + b - 2\),所以不可能出现环。
  2. 两种操作序列经过的数没有重合。
    同理,假如出现了重合,那么一定出现了环。

那么我们只需要求出这两种操作序列分别能过经过多少数即可。

以下拿 \(+a, -b\) 来考虑。

什么时候不能 \(+a, -b\)?设位置为 \(x\),那么说明 \(x + a > m, x - b < 0\),即 \(x \in [m - a + 1, b - 1]\)

那么我们考虑将 \(+a, -b\) 的操作改写为:我们进行了 \(k\)\(+a\),进行了若干次 \(-b\),最后位置落到了 \((v + ka) \bmod b\) 的位置。那么我们要求的实际就是一个最小的非负整数 \(k\),满足 \((v + ka) \bmod b \in [m - a + 1, b - 1]\)

首先我们将 \(v\) 独立出来。假如 \((v \bmod b) + a > m\),那么说明只能 \(-b\) 不能 \(+a\),那么能经过的数有 \(\left\lfloor\frac{v}{b}\right\rfloor\) 个,直接特判掉。

然后我们给出一个结论:\((v + ka) \bmod b = (v \bmod b) + (ka \bmod b)\)

证明此结论只需要证明 \((v\bmod b) + (ka \bmod b) < b\)。假如 \((v \bmod b) + (ka \bmod b) \ge b\),那么就有 \((v \bmod b) + a + (ka \bmod b) - b\le (v \bmod b) + a \le m\),那么也就是说,当前还可以继续 \(+a\),说明此时 \((v + ka) \bmod b \not \in [m - a + 1, b - 1]\),矛盾。

那么我们就可以转化为求最小的非负整数 \(k\) 满足 \(ka \bmod b \in [m - a + 1 - (v \bmod b), b - 1 - (v \bmod b)]\)

一般化这个问题,求最小的非负整数 \(k\) 满足 \(ka \bmod b \in [l, r]\)

\[ka - b \left\lfloor\frac{ka}{b}\right\rfloor \in [l, r] \]

这种带向下取整的式子考虑类欧一类的做法,那么我们把 \(b\) 拆开,即 \(b = (b \bmod a) + a \left\lfloor\frac{b}{a}\right\rfloor\),那么有:

\[\begin{aligned} ka - b \left\lfloor\frac{ka}{b}\right\rfloor &\in [l, r]\\ ka - (b \bmod a) \left\lfloor\frac{ka}{b}\right\rfloor + a \left\lfloor\frac{b}{a}\right\rfloor\left\lfloor\frac{ka}{b}\right\rfloor &\in [l, r]\\ (k + \left\lfloor\frac{b}{a}\right\rfloor\left\lfloor\frac{ka}{b}\right\rfloor) a - (b \bmod a) \left\lfloor\frac{ka}{b}\right\rfloor &\in [l, r]\\ (b \bmod a) \left\lfloor\frac{ka}{b}\right\rfloor &\in \left[(k + \left\lfloor\frac{b}{a}\right\rfloor\left\lfloor\frac{ka}{b}\right\rfloor) a - r, (k + \left\lfloor\frac{b}{a}\right\rfloor\left\lfloor\frac{ka}{b}\right\rfloor) a - l\right]\\ \end{aligned} \]

那么我们只需要找出最小的 \(\left\lfloor\frac{ka}{b}\right\rfloor\) 即可。

假如我们按照每 \(a\) 个数分块,那么假如 \(l-1, r\) 不在同一块内,也就意味着存在 \(ak \in [l, r]\),那么我们可以直接得出答案。否则,我们确定 \(l, r\) 在同一块内,那么我们就可以直接将区间两个端点对 \(a\) 取模,那么就有:

\[(b \bmod a) \left\lfloor\frac{ka}{b}\right\rfloor \bmod a \in \left[(a - r) \bmod a, (a - l) \bmod a \right] \]

然后我们发现这就从 \((a, b)\) 递归到 \((b \bmod a, a)\) 的子问题上来了。容易得出复杂度为 \(O(\log \max\{a, b\})\)

我们求出 \(\left\lfloor\frac{ka}{b}\right\rfloor\) 后,就能知道 \(ka \in [l + b \left\lfloor\frac{ka}{b}\right\rfloor, r + b \left\lfloor\frac{ka}{b}\right\rfloor]\),也就能得知 \(k\) 了。

最后我们求出 \(k\) 后,我们知道 \(+a\) 的次数为 \(k\) 次,\(-b\) 次数为 \(\lfloor\frac{v+ka}{b}\rfloor\)

然后这道题就解决了。

#include <bits/stdc++.h>
using namespace std;
int T, a, b, v, m;
// find the minimum k that ak mod b \in [l, r]
int solve(int a, int b, int l, int r) {
    if (a == 0) return 0;
    a %= b;
    if ((l - 1) / a != r / a) return (l + a - 1) / a;
    int t = solve(b, a % b, (a - r % a) % a, (a - l % a) % a);
    return (1ll * t * b + l + a - 1) / a;
}
// find the number that can be achived by +a, -b
int calc(int v, int a, int b) {
    int v0 = v % b;
    if (v0 + a > m) return v / b;
    int k = solve(a, b, m - a + 1 - v0, b - 1 - v0);
    return k + (v + 1ll * k * a) / b;
}
int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d%d%d", &a, &b, &v, &m);
        if (m >= a + b - 1) {
            printf("%d\n", m + 1);
        } else {
            printf("%d\n", calc(v, a, b) + calc(v, b, a) + 1);
        }
    }
    return 0;
}