第i个位置的牌是a[i],一次交换后第i个位置的牌变成a[a[i]]。
序列所有位置经过一次交换为一次交换,
已知交换m次之后的序列,求原先序列
思路:
给出a[i]为4 7 5 6 1 2 3
进行一次变换
1 2 3 4 5 6 7 4 7 5 6 1 2 3 1 2 3 4 5 6 7
* =
4 7 5 6 1 2 3 6 3 1 2 4 7 5 6 3 1 2 4 7 5
进行二次变换
1 2 3 4 5 6 7 6 3 1 2 4 7 5 1 2 3 4 5 6 7
* =
6 3 1 2 4 7 5 7 1 6 3 2 5 4 7 1 6 3 2 5 4
进行三次变换
1 2 3 4 5 6 7 7 1 6 3 2 5 4 1 2 3 4 5 6 7
* =
7 1 6 3 2 5 4 4 7 5 6 1 2 3 4 7 5 6 1 2 3
则进行三次变换后得到4 7 5 6 1 2 3
原序列在第三次变换的时候出现了循环
考虑一般情况。
因为原序列为1~N个不同的数,则序列能构成至少一个置换群,
则经过多次变换后肯定
会出现循环,
现在我们求出置换的循环节,已知新的序列,和进行交换的次数,
则再进行res - s % res
次交换即可得到原序列。
//res为循环节,s为给出的变换次数
#include <stdio.h> #include <string.h> int Array[1010],ArrayA[1010],ArrayB[1010]; void GetNext(int n) { for(int i = 1; i <= n; i++) ArrayB[i] = ArrayA[ArrayA[i]]; for(int i = 1; i <= n; i++) ArrayA[i] = ArrayB[i]; } bool IsSame(int n) { for(int i = 1; i <= n; i++) if(ArrayB[i]!=Array[i]) return false; return true; } int main() { int n,s; while(~scanf("%d%d",&n,&s)) { for(int i = 1; i <= n; i++) { scanf("%d",&Array[i]); ArrayA[i] = Array[i]; } int res; for(res = 1;;res++) { GetNext(n); if(IsSame(n)) break; } int m = res - s % res; int num = 0; while(num < m) { GetNext(n); num++; } for(int i = 1; i <= n; i++) printf("%d ",ArrayB[i]); } return 0; } ———————————————— 版权声明:本文为CSDN博主「行走少年郎」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/lianai911/article/details/39323335