#include<iostream>
#include<algorithm>
#include<numeric>//accumulate(be,en,0)
#include<cstring>//rfind("string"),s.find(string,begin)!=s.npos,find_first _of(),find_last_of()
#include<string>//to_string(value),s.substr(int begin, int length);
#include<cstdio>
#include<cmath>
#include<vector>//res.erase(unique(res.begin(), res.end()), res.end()),reverse(q.begin(),q.end());
#include<queue>//priority_queue(big) /priority_queue<int, vector<int>, greater<int>> q(small)
#include<stack>
#include<map>//unordered_map
#include<set>//iterator,insert(),erase(),lower(>=)/upper_bound(>)(value)/find()return end()
#include<unordered_map>
#include<unordered_set>
//#include<ext/pb_ds/assoc_container.hpp>//gp_hash_table
//#include<ext/pb_ds/hash_policy.hpp>
//using namespace __gnu_pbds;
#define int long long//__int128 2^127-1(GCC)
#define PII pair<int,int>
#define f first
#define s second
using namespace std;
const int inf = 1e17, N = 1e5 + 5;
int disa[N][3], disb[N][3], disc[N][3];
int lena[3], lenb[3], lenc[3];
int exgcd(int a, int b, int& x, int& y)
{
if (b == 0) {
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, x, y);
int z = x;
x = y;
y = z - y * (a / b);
return d;
}
int excrt(int m[], int r[])//中国剩余定理模板
{
int m1, m2, r1, r2, p, q;
m1 = m[0], r1 = r[0];
for (int i = 1; i < 3; i++) {
m2 = m[i], r2 = r[i];
int d = exgcd(m1, m2, p, q);
if ((r2 - r1) % d != 0) return -1;
p = p * (r2 - r1) / d;
p = (p % (m2 / d) + (m2 / d)) % (m2 / d);
r1 = m1 * p + r1;
m1 = m1 * m2 / d;
}
return (r1 % m1 + m1) % m1;
}
int solve(int x, int y, int z,int wc)
{
if (disa[x][wc] == -1 || disb[y][wc] == -1 || disc[z][wc] == -1) return inf;
//如果某个状态到达不了就返回inf
//后面设他们最小值q
//q=dis(mod len)中国剩余定理
int m[] = { lena[wc],lenb[wc],lenc[wc] };
int r[] = { disa[x][wc],disb[y][wc],disc[z][wc] };
int A = excrt(m, r);//如果中国剩余定理无解的话返回-1其他情况就返回他们的解
return A == -1 ? inf : A;
}
signed main()
{
ios_base::sync_with_stdio(0); cin.tie(0), cout.tie(0);
int n;
cin >> n;
vector<int>a(n + 5), b(n + 5), c(n + 5);
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> b[i];
for (int i = 1; i <= n; i++) cin >> c[i];
vector<int>abc(n + 5), bca(n + 5), cab(n + 5);
//记录每一个数经过3次迭代后所能到达的状态
for (int i = 1; i <= n; i++) abc[i] = a[b[c[i]]];
for (int i = 1; i <= n; i++) bca[i] = b[c[a[i]]];
for (int i = 1; i <= n; i++) cab[i] = c[a[b[i]]];
memset(disa, -1, sizeof disa);
memset(disb, -1, sizeof disb);
memset(disc, -1, sizeof disc);
//将a,b,c分成3组分别是3*k(0),3*k+1(1),3*k+2(2)
//因为它为n个数所以最终经过3*k次迭代必回回到之前标记过的某个数组
//len代表经过k次循环可以会到原来
for (int i = 1; disa[i][0] == -1; i = abc[i], lena[0]++) disa[i][0] = lena[0];
for (int i = 1; disb[i][0] == -1; i = bca[i], lenb[0]++) disb[i][0] = lenb[0];
for (int i = 1; disc[i][0] == -1; i = cab[i], lenc[0]++) disc[i][0] = lenc[0];
for (int i = a[1]; disa[i][1] == -1; i = abc[i], lena[1]++) disa[i][1] = lena[1];
for (int i = b[1]; disb[i][1] == -1; i = bca[i], lenb[1]++) disb[i][1] = lenb[1];
for (int i = c[1]; disc[i][1] == -1; i = cab[i], lenc[1]++) disc[i][1] = lenc[1];
for (int i = a[b[1]]; disa[i][2] == -1; i = abc[i], lena[2]++) disa[i][2] = lena[2];
for (int i = b[c[1]]; disb[i][2] == -1; i = bca[i], lenb[2]++) disb[i][2] = lenb[2];
for (int i = c[a[1]]; disc[i][2] == -1; i = cab[i], lenc[2]++) disc[i][2] = lenc[2];
int t;
cin >> t;
while (t--)
{
int x, y, z;
cin >> x >> y >> z;
//分成3*k(0),3*k+1(1),3*k+2(2)去讨论他是否有解,切最小值是多少
int m0 = solve(x, y, z, 0);
int m1 = solve(x, y, z, 1);
int m2 = solve(x, y, z, 2);
int ans = min({ m0 * 3,m1 * 3 + 1,m2 * 3 + 2 });
if (ans >= inf) cout << -1 << '\n';
else cout << ans << '\n';
}
}
Three Permutations
最新推荐文章于 2024-07-11 21:13:07 发布