主要思路
自己推了三个假的循环,遂奔向题解。
先考虑设循环节为 \(k\),且考虑最终 \(x = 0, y = 0\) 的局势。我们考虑怎样的循环节才能迭代一次、得到同样的 \(x = 0, y = 0\) 的局势。不妨直接带入 \(k\):
\[ x = (k + \lfloor \frac{k}{B} \rfloor) \bmod A, y = k \bmod B \]
此时终局势为 \(x = 0, y = 0\),那么可以得到信息 \(B | k\)。此时下取整已经没有效益,得:
\[ \begin{aligned} k + \frac{k}{B} &\equiv 0 \pmod A \\ k(B + 1) &\equiv 0 \pmod A \end{aligned} \]
算完这玩意之后,我们可以突破模意义的限制得到:
\[ \begin{aligned} k(B + 1) &= Ai \\ k &= i \cdot \frac{A}{B + 1} \end{aligned} \]
由于 \(k\) 是个整数,则 \(i\) 需要满足:
\[ i = j \frac{B + 1}{\gcd(A, B + 1)} \]
再加上 \(B | k\) 的条件,很容易得到:
\[ i = j B \frac{B + 1}{\gcd(A, B + 1)} \]
那么循环节就是:
\[ \begin{aligned} k &= j B \frac{B + 1}{\gcd(A, B + 1)} \cdot \frac{A}{B + 1} \\ &= j \frac{AB}{\gcd(A, B + 1)} \\ k &\equiv 0 \pmod {\frac{AB}{\gcd(A, B + 1)}} \end{aligned} \]
代码
// LOJ3144.cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX_N = 1e6 + 200;
ll n, A, B, loop, cnt;
pair<ll, ll> segs[MAX_N << 1];
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
int main()
{
scanf("%lld%lld%lld", &n, &A, &B);
loop = A / gcd(A, B + 1) * B;
for (int i = 1; i <= n; i++)
{
ll l, r;
scanf("%lld%lld", &l, &r);
if (r - l + 1 >= loop)
printf("%lld\n", loop), exit(0);
l %= loop, r %= loop;
if (l <= r)
segs[++cnt] = make_pair(l, r);
else
segs[++cnt] = make_pair(l, loop - 1), segs[++cnt] = make_pair(0, r);
}
sort(segs + 1, segs + 1 + cnt);
segs[++cnt] = make_pair(loop + 1, 0);
ll lft = segs[1].first, rig = segs[1].second, ans = 0;
for (int i = 2; i <= cnt; i++)
{
if (rig < segs[i].first)
{
ans += rig - lft + 1;
lft = segs[i].first, rig = segs[i].second;
}
else
rig = max(rig, segs[i].second);
}
printf("%lld\n", ans);
return 0;
}