题面
题意: 给定三个长度为 n n n的排列 a , b , c a,b,c a,b,c, ( x , y , z ) (x,y,z) (x,y,z) , 最开始为 ( 1 , 1 , 1 ) (1,1,1) (1,1,1),每过一秒变为 ( a y , b Z , c x ) (a_y,b_Z,c_x) (ay,bZ,cx)。 q q q次询问求变成 ( x , , y , , z , ) (x^,,y^,,z^,) (x,,y,,z,)的最短时间。
考试时看这样的连接关系以为会是一道图论,并且过的人非常少,就没有仔细想这道题,但其实这题是一道可做的数学题。
Solution:
性质:每过三秒 ( x , y , z ) (x,y,z) (x,y,z)会变为 ( a b c x , b c a y , c b a z ) (a_{b_{c_x}},b_{c_{a_{y}}},c_{b_{a_z}}) (abcx,bcay,cbaz),用复合关系表示为 ( a ∘ b ∘ c ( x ) , b ∘ c ∘ a ( y ) , c ∘ b ∘ a ( z ) ) (a\circ b\circ c(x),b\circ c\circ a(y),c\circ b\circ a(z)) (a∘b∘c(x),b∘c∘a(y),c∘b∘a(z)) 。
分别设这三个复合关系为 f a = a ∘ b ∘ c , f b = b ∘ c ∘ a , f c = c ∘ b ∘ a fa=a\circ b\circ c,fb=b\circ c\circ a,fc=c\circ b\circ a fa=a∘b∘c,fb=b∘c∘a,fc=c∘b∘a 。即每三秒 ( x , y , z ) (x,y,z) (x,y,z)会变为 ( f a ( x ) , f b ( y ) , f c ( z ) ) (fa(x),fb(y),fc(z)) (fa(x),fb(y),fc(z)) 。
我们考虑到在朴素情况下,数对 ( 1 , 1 , 1 ) (1,1,1) (1,1,1)不会同时第一次通过变换到达 ( x , y , z ) (x,y,z) (x,y,z),即三个位置上的数一次或多次分别到达了 x , y , z x,y,z x,y,z。
因此我们可以线性计算出三个位置的数,通过 f a , f b , f c fa,fb,fc fa,fb,fc变换,第一次分别变换到 x , y , z x,y,z x,y,z的时间 α 1 , α 2 , α 3 \alpha_1,\alpha_2,\alpha_3 α1,α2,α3,三个位置从 1 1 1变换回 1 1 1的时间为 m 1 , m 2 , m 3 m_1,m_2,m_3 m1,m2,m3。
则三个位置同时到达 ( x , y , z ) (x,y,z) (x,y,z)的时间 T T T满足 T ≡ α i ( m o d m i ) T\equiv \alpha_i(\mod m_i) T≡αi(modmi) 。
这是一个由三个同余方程构成的一元线性同余方程组,由于不保证模数为质数,我们用 e x c r t excrt excrt进行求解即可。
上面求解了从第 0 0 0秒开始进行的 f a , f b , f c fa,fb,fc fa,fb,fc变换,由于一次 f f f变换需要三秒,因此我们枚举起始时间为 0 , 1 , 2 0,1,2 0,1,2的情况,进行三次求解,即可求得所有解。
细节处理:
对于求解 α i \alpha_i αi ,标程中给了一个较好的处理,预处理出三个 d i s dis dis数组, d i s a / b / c i disa/b/c_i disa/b/ci代表从 1 1 1到 i i i需要通过几次 f a / b / c fa/b/c fa/b/c变换得到,值为 − 1 -1 −1即为不可到达。
因此求解 α i \alpha_i αi时只需要将 d i s a / b / c x / y / z disa/b/c_{x/y/z} disa/b/cx/y/z赋值给 α 1 / 2 / 3 \alpha_{1/2/3} α1/2/3即可。
对于无解情况有两种,第一种情况是通过 f a / b / c fa/b/c fa/b/c操作根本无法从 1 1 1变换到题目中给定的 x / y / z x/y/z x/y/z,即 d i s a / b / c x / y / z = − 1 disa/b/c_{x/y/z}=-1 disa/b/cx/y/z=−1,此时无解。
第二种情况是 e x c r t excrt excrt的无解条件,即合并方程 x ≡ a i ( m o d m i ) x\equiv a_i\pmod {m_i} x≡ai(modmi)与 x ≡ A ( m o d M ) x\equiv A\pmod M x≡A(modM)时, A A A与 a i a_i ai不满足 e x g c d exgcd exgcd的有解条件,即 g c d ( m i , M ) ∤ A − a i gcd(m_i,M)\nmid A-a_i gcd(mi,M)∤A−ai。
代码↓
#include
#define N 100100
using namespace std;
typedef long long ll;
const ll inf=1e18;
inline void read(ll &x){
ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
x=s*w;
}
ll n,q,x,y,z,flag;
ll a[N],b[N],c[N];
ll fa[N],fb[N],fc[N],disa[N],disb[N],disc[N];
ll ia[N],ib[N],ic[N];
ll mod[3],arr[3];
ll gcd(ll a, ll b){
return b?gcd(b,a%b):a;
}
void exgcd(ll &x, ll &y, ll a, ll b){
if(!b){x=1,y=0;return ;}
exgcd(y,x,b,a%b);
y-=a/b*x;
}
ll excrt(){
ll A=arr[0],M=mod[0];
for(ll i=1;i<=2;i++){
ll p,q,a,b,c,g;
a=M,b=mod[i],c=(arr[i]-A%b+b)%b,g=gcd(a,b);
if(c%g)return inf;
a/=g,b/=g,c/=g;
exgcd(p,q,a,b);
p=(p*c)%b;
A+=M*p;M*=b;
A=(A%M+M)%M;
}
return A;
}
ll solve(ll x, ll y , ll z){
if(disa[x]==-1||disb[y]==-1||disc[z]==-1)return inf;
arr[0]=disa[x],arr[1]=disb[y],arr[2]=disc[z];
return excrt();
}
int main(){
read(n);
for(ll i=1;i<=n;i++)read(a[i]),ia[a[i]]=i;
for(ll i=1;i<=n;i++)read(b[i]),ib[b[i]]=i;
for(ll i=1;i<=n;i++)read(c[i]),ic[c[i]]=i;
for(ll i=1;i<=n;i++){
fa[i]=a[b[c[i]]];
fb[i]=b[c[a[i]]];
fc[i]=c[a[b[i]]];
}
memset(disa,-1,sizeof disa);
memset(disb,-1,sizeof disb);
memset(disc,-1,sizeof disc);
for(ll i=1;disa[i]==-1;i=fa[i],mod[0]++)disa[i]=mod[0];
for(ll i=1;disb[i]==-1;i=fb[i],mod[1]++)disb[i]=mod[1];
for(ll i=1;disc[i]==-1;i=fc[i],mod[2]++)disc[i]=mod[2];
read(q);
for(ll i=1;i<=q;i++){
read(x),read(y),read(z);
ll ans=inf;
for(ll j=0;j<=2;j++){
ans=min(ans,solve(x,y,z)*3+j);
ll t=y,p=x;
x=ic[z],y=ia[p],z=ib[t];
}
if(ans==inf)puts("-1");
else printf("%lld\n",ans);
}
}