給定置換後的序列(第 s 次置換後),求原始序列。置換規則:位置 i 的元素移動到位置 a[i]。
T 使得 P^T = I(恆等置換)。s 次置換後的序列 B = P^s(A),求 A = P^{-s}(B) = P^{T - s%T}(B)。T(或直接模擬直到回到初始)。B 執行 (T - s%T) 次置換得到 A。#include <cstdio>
#include <cstring>
int a[1010], b[1010], c[1010];
int main() {
int n, s;
while (~scanf("%d%d", &n, &s)) {
for (int i=1;i<=n;i++) scanf("%d",&a[i]), b[i]=a[i], c[i]=a[i];
int cycle = 0;
do { // 求循環節
cycle++;
for (int i=1;i<=n;i++) b[i] = c[c[i]];
for (int i=1;i<=n;i++) c[i] = b[i];
} while (memcmp(a, b, sizeof(a)) != 0); // 直到回到初始
s %= cycle; s = cycle - s; // 逆操作次數
while (s--) {
for (int i=1;i<=n;i++) b[i] = a[a[i]];
for (int i=1;i<=n;i++) a[i] = b[i];
}
for (int i=1;i<=n;i++) printf("%d\n", a[i]);
}
return 0;
}
O(T·n),T 通常很小(≤ n)。O(s·n),s < T。O(n²) 以內,n≤1000 極快。