難しくはないけど細かいところが面倒な問題。
https://codeforces.com/contest/1500/problem/B
問題
2つの整数列A,Bが与えられる。
各数列内では、同じ値は1回しか登場しない。
i個目の整数ペアを、A[i%|A|]とB[i%|B|]とする。
ペアの値が異なるのがK回目となるのは、何個目の整数ペアか。
解法
解をRとしたとき、二分探索で求めることを考える。
考えた整数ペアのうち、R個目までのペアうち、値が一致するペアの登場回数を求めよう。
これは、A,B両方に登場する値について、R個目までのペアにその値のペアが何回登場するかを求めればよい。
中国人剰余定理を用いれば、初回両者がペアになるタイミングとその後の周期がわかるので、その値のペアの登場回数が計算できる。
int N,M; ll K; int A[505050],B[505050]; int P[1010101]; int Q[1010101]; pair<ll,ll> C[1010101]; ll ext_gcd(ll p,ll q,ll& x, ll& y) { // get px+qy=gcd(p,q) if(q==0) return x=1,y=0,p; ll g=ext_gcd(q,p%q,y,x); y-=p/q*x; return g; } pair<ll,ll> crt(ll a1,ll mo1,ll a2,ll mo2) { // return (x,y) y=lcm(a1,a2),x%mo1=a1,x%mo2=a2 ll g,x,y,z; g=ext_gcd(mo1,mo2,x,y); a1=(a1%mo1+mo1)%mo1;a2=(a2%mo2+mo2)%mo2; if(a1%g != a2%g) return pair<ll,ll>(-1,0); // N/A __int128_t lcm=mo1*(mo2/g); if(lcm<mo1) return pair<ll,ll>(-2,0); // overflow __int128_t v=a1+((a2-a1)%lcm+lcm)*x%lcm*(mo1/g); return make_pair(((v%lcm)+lcm) % lcm,lcm); } ll fail(ll d) { int i; ll tot=0; FOR(i,1010000) if(P[i]>=0&&Q[i]>=0) { if(C[i].first==0&&C[i].second==0) { C[i]=crt(P[i],N,Q[i],M); } if(C[i].first<0) continue; auto& p=C[i]; if(p.first<=d) { ll x=(d-p.first)/p.second; while(p.first+x*p.second>=d) x--; while(p.first+(x+1)*p.second<d) x++; tot+=x+1; } } return d-tot; } void solve() { int i,j,k,l,r,x,y; string s; MINUS(P); MINUS(Q); cin>>N>>M>>K; FOR(i,N) { cin>>A[i]; P[A[i]]=i; } FOR(i,M) { cin>>B[i]; Q[B[i]]=i; } ll ret=1LL<<60; for(i=59;i>=0;i--) if(fail(ret-(1LL<<i))>=K) ret-=1LL<<i; cout<<ret<<endl; }
まとめ
まぁでも本番割とすんなり解けてたようだ。