题意
- 给你一个初始为1,2,...,n1, 2, ..., n1,2,...,n的排列,一个置换AAA,一个排列BBB,询问是否可以通过初始序列置换到序列BBB.
首先根据相关知识可以知道一组置换是一个环
分别考虑每一个数
如果iii和bib_ibi不在一个环中,那么就肯定无解了
不然那置换次数kkk一定满足k=bi到i的变换步数(mod环的大小)k = b_i到i的变换步数(mod环的大小)k=bi到i的变换步数(mod环的大小)
这样子列出了很多个方程 那我们接下来就是判断方程是否有解的问题
对于两个方程x=a1 mod b1,x=a2 mod b2x = a_1 \ mod \ b_1, x = a_2 \ mod \ b_2x=a1 mod b1,x=a2 mod b2
设b3b_3b3为b1,b2b_1,b_2b1,b2的一个公约数
那么当且仅当a1=a2(mod b3)a_1 = a_2(mod \ b_3)a1=a2(mod b3)的时候
方程组才有解 这个东西我不会证明
但如果把模运算当做减法运算来理解不是很难
我们所以只要枚举约数再枚举它的倍数就好了
时间复杂度O(nlnn)O(n \ln n)O(nlnn)
Codes
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, a[N], b[N], size[N], dep[N], be[N], val[N];
void dfs(int x, int fa) {
++ size[fa], be[x] = fa;
if(!dep[a[x]]) {
dep[a[x]] = dep[x] + 1;
dfs(a[x], fa);
}
}
void Init() {
for(int i = 1; i <= n; ++ i)
scanf("%d", &a[i]), size[i] = 0, val[i] = -1;;
for(int i = 1; i <= n; ++ i)
scanf("%d", &b[i]), dep[i] = 0;
for(int i = 1; i <= n; ++ i)
if(!dep[i])
dep[i] = 1, dfs(i, i);
}
void Solve() {
for(int i = 1; i <= n; ++ i) {
if(be[i] != be[b[i]]) return void(puts("Forever"));
int now = be[i], tmp = dep[i] - dep[b[i]];
if(tmp <= 0) tmp += size[now];
if(val[size[now]] == -1) val[size[now]] = tmp;
else if(val[size[now]] != tmp) return void(puts("Forever"));
}
for(int i = 1; i <= n; ++ i) {
int now = -1, tmp;
for(int j = i; j <= n; j += i) {
if(val[j] == -1) continue;
tmp = val[j] % i;
if(now == -1) now = tmp;
else if(now != tmp) return void(puts("Forever"));
}
}
puts("Ever");
}
int main() {
#ifdef ylsakioi
freopen("ever.in", "r", stdin);
freopen("ever.out", "w", stdout);
#endif
while(scanf("%d", &n) != EOF)
Init(), Solve();
return 0;
}