B - Two chandeliers(扩展中国剩余定理+二分)

Posted CCSU_Cola

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了B - Two chandeliers(扩展中国剩余定理+二分)相关的知识,希望对你有一定的参考价值。

题意:有两个灯泡,灯泡都为变色灯,分别有n和m种颜色,每个颜色用ai和bi表示(ai互不相同,bi互不相同),灯每天按照序列顺序更换一次颜色,问多少天之后一共出现过k天两个灯的颜色互不相同。

思路:先将每个颜色出现在ai和bi中出现的位置存起来,然后根据扩展中国剩余定理,求相同的颜色第一次相同的位置pos%n==x&&pos%m==y,x和y分别表示该颜色在ai和bi中出现的位置,然后每个颜色下次相同的位置即为pos+lcm(n,m),通过这个可以求出某个位置之前该颜色出现的次数,二分答案,然后枚举减去所有颜色出现相同位置的次数,若大于等于k则说明在当前答案之前或者就是当前答案,否则在答案之后。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll bi[10],ai[10];
ll a[1000010],b[1000010],c[1000010];
ll n,m,k,len,LCM;
ll gcdd(ll a,ll b){
    return b==0? a:gcdd(b,a%b);
}
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0){x=1;y=0;return a;}
    ll gcd=exgcd(b,a%b,x,y);
    ll tp=x;
    x=y; y=tp-a/b*y;
    return gcd;
}
ll excrt()
{
    ll x,y,k;
    ll M=bi[1],ans=ai[1];//第一个方程的解特判
    for(int i=2;i<=2;i++)
    {
        ll a=M,b=bi[i],c=(ai[i]-ans%b+b)%b;//ax≡c(mod b)
        ll gcd=exgcd(a,b,x,y),bg=b/gcd;
        if(c%gcd!=0) return -1; //判断是否无解,然而这题其实不用
        
        x=((x*c)/gcd)%bg;
        ans+=x*M;//更新前k个方程组的答案
        M*=bg;//M为前k个m的lcm
        ans=(ans%M+M)%M;
    }
    return (ans%M+M)%M;
}
bool check(ll x){
    ll ans=0;
    for(int i=1;i<=len;i++){
        if (a[i]&&b[i]&&a[i]<=x&&b[i]<=x) {
            ll v=c[i];
            if(v!=-1&&x>=v){
                ans+=(x-v)/LCM;
                if (v>0)ans++;
            }
        }
    }
    if(x-ans<k) return false;
    return true;
}
int main(){
    scanf("%lld%lld%lld",&n,&m,&k);
    int x;
    for(int i=1;i<=n;i++){
        scanf("%d",&x);
        a[x]=i;
    }
    for(int j=1;j<=m;j++){
        scanf("%d",&x);
        b[x]=j;
    }
    LCM=(n*m)/(gcdd(n,m)*1ll);
    len=2*max(n,m);
    for(int i=1;i<=len;i++){
        if(a[i]&&b[i]){
            bi[1]=n,bi[2]=m;
            ai[1]=a[i],ai[2]=b[i];
            c[i]=excrt();
        }
    }
    ll l=1,r=2*max(n,m)*k,ans;
    while(l<=r){
        ll mid=(l+r)>>1;
        if(check(mid)){
            ans=mid;
            r=mid-1;
        }
        else l=mid+1;
    }
    printf("%lld\\n",ans);
}

以上是关于B - Two chandeliers(扩展中国剩余定理+二分)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 710 D. Two Arithmetic Progressions

UVA11540 Sultan's Chandelier

POJ 2161 Chandelier(树状DP)

扩展欧几里得及中国剩余定理

CQOJ 扩展中国剩余定理 数论

扩展中国剩余定理