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(扩展中国剩余定理+二分)的主要内容,如果未能解决你的问题,请参考以下文章