题意
给两个数组 a
和 b
,长度分别为 (n),(m),每个数组中不含相同的数,且各自不断循环,问第 (k) 次不同是在第几天。((1≤n,m≤5 imes10^5;1≤k≤10^{12},1≤a_i,b_i≤2⋅max(n,m)))。题目链接:https://codeforces.com/contest/1501/problem/D
分析
假设 a
数组中 (a_i) 和 b
数组中 (b_j) 相等,那么可以列出方程:(xn+i=ym+j) 。如果方程有解,说明有很多天,(a_i) 和 (b_j) 是相等的且处于同一天。否则,表示二者不可能出现在同一天。对每个数都统计完之后,只有这些数会对第 (k) 次不同出现的天数产生影响。用数字存下这些数在 (lcm(n,m)) 天内,同时出现是在哪一天,每一个 (lcm) 为一个周期,出现一次。之后,采用二分的方式求解,具体见代码(二分边界要大些)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5;
int a[N],b[N],pos[N<<1],cnt;
ll lcm,k,num[N];//num[N]开成了int型,但没有re,而是wa
int gcd(int x,int y)
{
return y==0?x:gcd(y,x%y);
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1,y=0;
return a;
}
ll res=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return res;
}
ll cal(ll a,ll b,ll c,ll d)//n,-m,
{
ll e=d-c;
ll x=0,y=0;
ll gcd=exgcd(a,b,x,y);
if(e%gcd) return -1;
x=e/gcd*x;
if(b<0) b=-b;
b/=gcd;
x=(x%b+b)%b;//最小正整数解
ll ans=x*a+c;
return ((ans-1)%lcm+lcm)%lcm+1;//在一个lcm内
//WA:(ans-1)%lcm+1
}
bool check(ll mid)
{
ll res=0;
for(int i=1;i<=cnt;i++)
//if(mid>=num[i]) res+=((mid-num[i])/lcm+1);
res+=(mid/lcm+((mid%lcm)>=num[i]));//
return (mid-res>=k);
}
int main()
{
int n,m;
scanf("%d%d%lld",&n,&m,&k);
lcm=1LL*n*m/gcd(n,m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pos[a[i]]=i;
}
cnt=0;
for(int i=1;i<=m;i++)
{
scanf("%d",&b[i]);
if(pos[b[i]]>0)
{
ll res=cal(1LL*n,-1LL*m,1LL*pos[b[i]],1LL*i);cout<<"res="<<res<<endl;
if(res!=-1) num[++cnt]=res;
}
}
ll l=1,r=1e18;
while(l<=r)
{
ll mid=(l+r)>>1;
if(check(mid)) r=mid-1;
else l=mid+1;
}
printf("%lld
",l);
return 0;
}