「APIO2019」奇怪装置

Problem

传送门:左转 右转

Solution

至高无上的xxx250说这道题有循环节,且观察样例可大胆猜测周期一定是\(AB\)的因数。

题目要求求这一坨玩意:

\[\begin{cases} x=((t+\lfloor\frac{t}{B}\rfloor)\ \bmod A\\ y=(t\ \bmod B) \end{cases}\]

设循环节为\(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;
}
posted @ 2022-05-02 19:18  Thermalrays  阅读(54)  评论(2编辑  收藏  举报