[APIO2019] 奇怪装置

$solution:$

问题其实就是求两个式子的循环节。

钦定 $tmod B=0$且 $(t eq 0)$,其 $t$ 为循环节。

则将 $1$ 式拆开得 $frac{t imes (B+1)}{B}mod A=0$。

 $frac{t imes (B+1)}{B}equiv 0space(mod A)$

$frac{t}{B}equiv 0space (mod frac{A}{gcd(A,B+1)})$

$tequiv 0space (mod frac{A imes B}{gcd(A,B+1)})$。

即循环节为 $frac{A imes B}{gcd(A,B+1)}$

直接做线段覆盖即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=1000001;
int n,A,B,k;
int gcd(int a,int b){
    if(!b) return a;
    return gcd(b,a%b);
} 
struct node{
    int l,r;
}x[MAXN<<1];
int cnt,Ans;
bool cmp(node x1,node x2){return x1.l<x2.l;}
void debug(){
    for(int i=1;i<=cnt;i++) printf("l:%d r:%d
",x[i].l,x[i].r);
    return;
}
signed main(){
//    freopen("make.in","r",stdin);
    n=read(),A=read(),B=read();
    k=(A/gcd(A,B+1))*B;
    for(int i=1;i<=n;i++){
        int l=read(),r=read();
        if((r-l+1)>=k){printf("%lld
",k);return 0;}
        if(l==r){x[++cnt].l=l%k,x[cnt].r=l%k;continue;}
        if((l%k)<=(r%k)){x[++cnt].l=l%k,x[cnt].r=r%k;continue;}
        else{
            x[++cnt].l=l%k,x[cnt].r=k-1;
            x[++cnt].l=0,x[cnt].r=r%k;
        }
    }
    sort(x+1,x+cnt+1,cmp);
    int L=x[1].l,R=x[1].r;
    for(int i=2;i<=cnt;i++){
        if(x[i].l>R){Ans+=R-L+1;L=x[i].l,R=x[i].r;continue;}
        R=max(R,x[i].r);
    }Ans+=R-L+1;
    printf("%lld
",Ans);
}
View Code
原文地址:https://www.cnblogs.com/si-rui-yang/p/10932874.html