题意:
给出两个数组 a a a, b b b,长度分别为 n n n, m m m,第 i i i 时刻, a a a数组当前指向下标为 ( i − 1 ) % n + 1 (i-1) \% n+1 (i−1)%n+1 , b b b数组指向下标为 ( i − 1 ) % m + 1 (i-1) \% m+1 (i−1)%m+1
若两个数不同,则计数,当计数到达 k k k 时,求当前的时刻。
题解:
二分时刻,求出不同的数量,怎么求呢?
因为数组中的数两两不同,假设数 x x x 在 a a a 中的位置为 p o s 1 pos1 pos1,在 b b b中的位置为 p o s 2 pos2 pos2那么我们就要求一个最小的时刻 t t t ,满足
{ ( t − 1 ) ≡ ( p o s 1 − 1 ) ( m o d n ) ( t − 1 ) ≡ ( p o s 2 − 1 ) ( m o d m ) \left\{ \begin{aligned} (t-1) \equiv (pos1-1) (\mod n) \\ (t -1)\equiv (pos2-1) (\mod m) \\ \end{aligned} \right. {(t−1)≡(pos1−1)(modn)(t−1)≡(pos2−1)(modm)
解这个式子就是中国剩余定理,但 n , m n,m n,m不互质,所以要用扩展中国剩余定理即可。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int mod=1e9+7;
const int MAXN=1e6+5;
const int N=1e5+10;
int n,m;
int p1[MAXN],p2[MAXN];
ll dp[MAXN];
ll gcd(ll a,ll b) {
return b == 0 ? a : gcd(b,a%b);
}
ll exgcd(ll a,ll b,ll &x,ll &y) {
if(b == 0) {
x = 1,y = 0;
return a;
}
else {
ll res = exgcd(b,a%b,x,y);
ll t = x;
x = y;
y = t - a / b * y;
return res;
}
}
ll excrt(ll m1,ll m2,ll a1,ll a2) {
ll x,y,c,g;
c = a2 - a1;
g = exgcd(m1,m2,x,y);
x = x * c / g;
y = m2 / g;
x = (x % y + y) % y;
a1 = a1 + x * m1;
m1 = m1 * m2 / g;
return a1;
}
bool check(ll mid,ll k,ll lc){
ll res=0;
int maxx=max(n,m)*2;
for(int i=1;i<=maxx;i++){
if(!p1[i]||!p2[i]||!dp[i]) continue;
if(dp[i]<=mid){
res+=(mid-dp[i])/lc+1;
}
if(mid-res<k) return false;
}
return mid-res>=k;
}
int main()
{
ll k;
scanf("%d%d%lld",&n,&m,&k);
for(int i=1,x;i<=n;i++){
scanf("%d",&x);
p1[x]=i;
}
for(int i=1,x;i<=m;i++){
scanf("%d",&x);
p2[x]=i;
}
int maxx=max(n,m)*2;
int gc=gcd(n,m);
for(int i=1;i<=maxx;i++){
if(!p1[i]||!p2[i]) continue;
if(abs(p1[i]-p2[i])%gc!=0) continue;
dp[i]=excrt(n,m,p1[i],p2[i]);
}
ll l=k,r=1e18;
ll lc=1ll*n*m/gc;
ll ans;
while(l<=r){
ll mid=(l+r)>>1;
if(check(mid,k,lc)){
ans=mid;
r=mid-1;
}
else{
l=mid+1;
}
}
printf("%lld\n",ans);
}