版权声明:_ https://blog.csdn.net/lunch__/article/details/82807851
题意
- 给你一个初始为 的排列,一个置换 ,一个排列 ,询问是否可以通过初始序列置换到序列 .
首先根据相关知识可以知道一组置换是一个环
分别考虑每一个数
如果 和 不在一个环中,那么就肯定无解了
不然那置换次数 一定满足
这样子列出了很多个方程 那我们接下来就是判断方程是否有解的问题
对于两个方程
设 为 的一个公约数
那么当且仅当 的时候
方程组才有解 这个东西我不会证明
但如果把模运算当做减法运算来理解不是很难
我们所以只要枚举约数再枚举它的倍数就好了
时间复杂度
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;
}