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 扩展中国剩余定理 数论

扩展中国剩余定理