[APIO2019] 奇怪装置

$solution:$

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

钦定 $t\mod B=0$且 $(t\neq 0)$,其 $t$ 为循环节。

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

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

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

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

即循环节为 $\frac{A\times 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\n",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\n",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\n",Ans);
}
View Code

猜你喜欢

转载自www.cnblogs.com/si-rui-yang/p/10932874.html
今日推荐