Loading [MathJax]/extensions/tex2jax.js

LibreOJ#3144. 「APIO 2019」奇怪装置 – 题解

主要思路

自己推了三个假的循环,遂奔向题解。

先考虑设循环节为 \(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} \]

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 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;
}
// 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; }
// 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;
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *