# [APIO2019]奇怪装置。

## 题解

$ac \equiv bc(modp),(c,p)=d$$a \equiv b(mod \frac{p}{d})$
$\because ac ≡ bc(mod p)$
$\therefore p|ac-bc$
$\therefore p|c(a-b)$
$\because (c,p)=d$
$\therefore \frac{p}{d}|\frac{c}{d}(a-b)$
$\because c,p$已经除去了$gcd$
$\therefore (\frac{p}{d},\frac{c}{d})=1$

$\therefore \frac{p}{d}|a-b$
$a \equiv b(mod \frac{p}{d})$

$t=k$时，假设$x=0,y=0$(当前是第一次循环，循环节就是$k$)
$t$换成$k$
$x=((k+\lfloor \frac{k}{B} \rfloor)modA),y=(kmodB)$

$0=((k+\frac{k}{B})modA)$

$0=(\frac{k(B+1)}{B}modA)$

$0 \equiv \frac{k}{B} (mod \frac{A}{gcd(A,B+1)})$

$0 \equiv k (mod \frac{AB}{gcd(A,B+1)})$

$l$$r$都模$k$（下文的$l$$r$都是模$k$之后的）
$l <= r$

$[l,k - 1]$$[0,r]$

$L$的左端点$>nr$则说明这条线段已经与当前连通的线段所断开了，我们将答案加上$nr-nl+1$，然后将$nl$$nr$更新为这条线段的左端点和右端点即可。

## 代码

#include <bits/stdc++.h>

const int maxn = 1e6 + 10;
typedef long long ll;

template<class t> inline void read(t& res) {
res = 0;  char ch = getchar();  bool neg = 0;
while (!isdigit(ch))
neg |= ch == '-', ch = getchar();
while (isdigit(ch))
res = (res << 1) + (res << 3) + (ch & 15), ch = getchar();
if (neg)
res = -res;
}

ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }

ll n, m, i, j, k, A, B, sz, len, nl, nr;
ll ans;
struct line {
ll l, r;
line() { l = r = 0; }
line(ll _l, ll _r) { l = _l;  r = _r; }
inline friend bool operator < (line a, line b) {
return a.l < b.l;
}
} l[maxn << 1];

int main() {
len = A / gcd(A, B + 1) * B;
for (int i = 1; i <= n; i++) {
if (ri - le + 1 >= len) { printf("%lld\n", len);  return 0; }
le %= len;
ri %= len;
if (le <= ri)
l[++sz] = line(le, ri);
else
l[++sz] = line(le, len - 1),
l[++sz] = line(0, ri);
}
std::sort(l + 1, l + sz + 1);
l[++sz] = line(len + 1, 0);
nl = l[1].l, nr = l[1].r;
for (int i = 2; i <= sz; i++) {
if (nr < l[i].l) {
ans += nr - nl + 1;
nl = l[i].l;
nr = l[i].r;
} else {
nr = std::max(nr, l[i].r);
}
}
printf("%lld\n", ans);
return 0;
}

posted @ 2019-08-20 13:23  _connect  阅读(83)  评论(0编辑  收藏
Live2D