「APIO2019」奇怪装置
Problem
Solution
至高无上的xxx250说这道题有循环节,且观察样例可大胆猜测周期一定是\(AB\)的因数。
题目要求求这一坨玩意:
设循环节为\(k\),因为\(t=0\)时,\(\begin{cases} x=0 \\ y=0 \end{cases}\),所以,\(\begin{cases} x = ((k + \frac{k}{B})\ \bmod A) = 0\\ y = (k \ \bmod B) = 0 \end{cases}\)
即\(\begin{cases} 0 = (k + \frac{k}{B}) \ \bmod A \\ 0 = (k \ \bmod B) \end{cases}\)
因为\(0 = (k \ \bmod B)\) 所以式子中的向下取整可以去掉。\(0 = (k + \frac{k}{B}) \ \bmod A\)于是可化为\(0 = \frac{k(B+1)}{B} \ \bmod A\)
所以\(0 \equiv \frac{k(B+1)}{B} \ \bmod A\)
式子可化为\(0 \equiv \frac{k}{B} \ (\bmod \ \frac{A}{gcd(A,B+1)})\)
移项可得\(0 \equiv k \ (\bmod \ \frac{AB}{gcd(A,B+1)})\)
所以最小循环节为\(k(\bmod \ \frac{AB}{gcd(A,B+1)}) = 0\),所以\(k = \frac{AB}{gcd(A,B+1)}\)
然后题目所求可以转化为区间覆盖问题。
分类讨论亿一下,区间\([l,r]\)
若\(k \leq r - l + 1\),则答案为\(k\)
否则,设\(L = l \bmod k , R = r \bmod k\)。将点对映射到数轴上,将其转化为一个线段覆盖问题。(需要分别考虑\(L \leq R\)和\(L > R\)的情况)
\(code:\)
//最小循环节 + 线段覆盖
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX_N = 1000000 + 5;
int n,m;
ll A,B,k,ans;
struct node{
ll l,r;
}s[MAX_N];
inline bool cmp(node a,node b){
return a.l<b.l;
}
int main(){
scanf("%d%lld%lld",&n,&A,&B);
k=A/__gcd(A,B+1)*B;
if(k<0) k=2e18;
for(int i=1;i<=n;++i){
ll l,r;
scanf("%lld%lld",&l,&r);
if(r-l+1>=k){
ans=k;
continue;
}
else{
l%=k,r%=k;
if(l>r) s[++m]=(node){0,r},s[++m]=(node){l,k-1};
else s[++m]=(node){l,r};
}
}
if(ans){
printf("%lld\n",ans);
return 0;
}
sort(s+1,s+1+m,cmp);
ans=0;
ll L=s[1].l,R=s[1].r;
s[++m]=(node){k,k};
for(int i=2;i<=m;++i){
if(R<s[i].l){
ans+=R-L+1;
L=s[i].l,R=s[i].r;
}
else{
R=max(s[i].r,R);
}
}
printf("%lld\n",ans);
return 0;
}