#P2087. 置换的"循环节".填空题

置换的"循环节".填空题

题目描述
N 个数的全排列有 N! 种,比如 5 个数的排列有 5!=120 种。但是,前面的置换 ( 3 4 5 2 1 ) 我们看到,置换 6 次后,数列就还原了。

显然,置换( 3 4 5 2 1 )只能得到 6 个不同的排列,或称这个置换的周期是 6 。

当 N 比较大时,周期有可能回很大!

为了研究这个问题,数学家先简化问题:研究单独一个“数”的周期!

例如置换( 3 4 5 2 1 )的规律:

  1. 原始数列 1 2 3 4 5

  2. 第 1 次置换后 5 4 1 2 3

  3. 第 2 次置换后 3 2 5 4 1

  4. 第 3 次置换后 1 4 3 2 5

  5. 第 4 次置换后 5 2 1 4 3

  6. 第 5 次置换后 3 4 5 2 1

  7. 第 6 次置换后 1 2 3 4 5

......

因此:

  • 数字 1 的位置变化为:1—3—5—1—3—5—1…, 显然数字1的周期就是 3 。

  • 数字 2 的位置变化为:2—4—2—4—2—4…, 显然数字2的周期就是 2 。

  • 数字 3 的位置变化为:3—5—1—3—5—1—3…, 显然数字3的周期就是 3 。

  • 数字 4 的位置变化为:4—2—4—2—4—2…, 显然数字4的周期就是 2 。

......

结论:各个数的周期分别是:3 2 3 2 3。

输入格式

第一行 1 个正整数:N,范围在[1,100],表示字符串长度。

第二行:有 N 个整数,为 1 到N的一个全排列,表示一个置换。

输出格式

一行,N 个数。第 i 个数表示第 1 个数经过多少次又变化回来。

样例

5
5 3 2 1 4
3 2 2 3 3

解题思路分析

可以构造一个自定义函数,这个函数用来检查第 i 个数要跳转(置换)多少次之后回到 i。

完善程序

#include<bits/stdc++.h>
using namespace std;
int jump[101],n,ans[101];
int work(int i)
{
	int cnt=填空(1) ,ii=i; // 用 ii 备份 i 原来的值,后面还要用到
	i = jump[i]; // 最少跳 1 次 
	while(i!=ii) // 检查是否变回原来的 i 
	{
		i = 填空(2);
		cnt = 填空(3);
	}
	// 跳了 cnt 次就变回 i
	return cnt;
}
int main()
{
	
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&jump[i]);

	for(int i=1;i<=n;i++)
		printf("%d ",填空(4));
		
		
	return 0;
}

填空(1):{{ input(1) }}

填空(2):{{ input(2) }}

填空(3):{{ input(3) }}

填空(4):{{ input(4) }}