题意:
给定n的两个排列A和B,还有置换C,问最少需要对A进行多少次置换C才能变成B,不可能则输出Impossible
思路:
思路是比较好想的,难度在于怎么实现。。
对A中每个数A[i],求出它需要经过多少次置换能变成B[i],如果变不了就Impossible。
然后就是用CRT来合并就是答案了。
涨姿势了。。java的输入挂。。
import java.math.*;
import java.text.*;
import java.util.*;
import java.io.*;
class Scan {
BufferedReader buffer;
StringTokenizer tok;
Scan() {
buffer = new BufferedReader(new InputStreamReader(System.in));
tok = null;
}
boolean hasNext() {
while(tok == null || !tok.hasMoreElements()) {
try {
tok = new StringTokenizer(buffer.readLine());
} catch(Exception e) {
return false;
}
}
return true;
}
String next() {
if(hasNext()) return tok.nextToken();
return null;
}
int nextInt() {
String s = next();
return Integer.parseInt(s);
}
long nextLong() {
return Long.parseLong(next());
}
}
public class Main {
public static BigInteger K1, K2;
public static void exgcd(BigInteger a, BigInteger b) {
if(b.compareTo(BigInteger.ZERO) == 0) {
K1 = BigInteger.ONE;
K2 = BigInteger.ZERO;
}
else {
exgcd(b, a.mod(b));
BigInteger tmp = K1;
K1 = K2;
K2 = tmp;
K2 = K2.subtract(a.divide(b).multiply(K1));
}
}
public static void main(String []args) {
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
Scan scan = new Scan();
int N = 50020;
int a[] = new int[N], b[] = new int[N], c[] = new int[N], n;
boolean vis[] = new boolean[N];
int pos[] = new int[N];
int dep[] = new int[N];
int x[] = new int[N];
int t[] = new int[N], val[] = new int[N];
int mod[] = new int[N];
while(scan.hasNext()) {
n = scan.nextInt();
for(int i = 1; i <= n; ++i) {
a[i] = scan.nextInt();
pos[a[i]] = i;
}
for(int i = 1; i <= n; ++i)
b[i] = scan.nextInt();
for(int i = 1; i <= n; ++i)
c[i] = scan.nextInt();
for(int i = 1; i <= n; ++i) {
vis[i] = false;
dep[i] = -1;
mod[i] = -1;
}
boolean flag = true;
int tot = 0;
for(int i = 1; i <= n; ++i) {
if(!vis[a[i]]) {
int cnt = 0;
int u = c[i];
x[++cnt] = a[i];
dep[a[i]] = 0;
int d = 0;
while(u != i) {
dep[a[u]] = ++d;
vis[a[u]] = true;
// System.out.println("dep " + a[u] + " " + dep[a[u]]);
x[++cnt] = a[u];
u = c[u];
}
for(int j = 1; j <= cnt; ++j) {
//System.out.println("x[j] " + x[j]);
int v = pos[x[j]];
if(dep[b[v]] == -1) {
flag = false;
break;
}
val[++tot] = dep[a[v]] - dep[b[v]];
if(val[tot] < 0) val[tot] += cnt;
if(mod[cnt] != -1 && mod[cnt] != val[tot]) {
flag = false;
break;
}
mod[cnt] = val[tot];
}
for(int j = 1; j <= cnt; ++j) {
int v = pos[x[j]];
dep[a[v]] = -1;
}
if(flag == false) break;
}
}
if(!flag) {
System.out.println("Impossible");
continue;
}
BigInteger M1 = BigInteger.ONE;
BigInteger B1 = BigInteger.ZERO;
for(int i = 2; i <= n; ++i) {
if(mod[i] == -1) continue;
//System.out.println("i " + i + "mod " + mod[i]);
BigInteger M2 = BigInteger.valueOf(i);
BigInteger B2 = BigInteger.valueOf(mod[i]);
BigInteger g = M2.gcd(M1);
BigInteger X = B2.subtract(B1);
if(X.mod(g).compareTo(BigInteger.ZERO) != 0) {
flag = false;
break;
}
exgcd(M1.divide(g), M2.divide(g));
// System.out.println(K1 + " " + K2);
K1 = K1.multiply(X.divide(g));
B1 = B1.add(K1.multiply(M1));
M1 = M1.divide(g).multiply(M2);
B1 = B1.mod(M1);
if(B1.compareTo(BigInteger.ZERO) < 0) B1 = B1.add(M1);
// System.out.println("B1 M1" + B1 + " " + M1);
}
if(!flag) {
System.out.println("Impossible");
continue;
}
System.out.println(B1);
}
}
}