1 条题解
-
0
题意分析
本题围绕集合的置换(排列)概念展开。置换是集合到自身的一一映射,即对集合元素的一种重新排序方式。例如,对于集合{1, 2, 3, 4, 5},可以通过特定记录定义置换,如,,等。
在此基础上,定义,,像。存在一种特殊置换,它使集合中元素保持不变,且对于任意,有。
重要结论是:对于个元素集合的任意置换,存在自然数,使得,满足此条件的最小自然数被称为置换的阶。
题目要求编写程序,给定一个置换,求出其阶。输入时,第一行是集合元素个数(),第二行是个1到的自然数,代表置换。输出为该置换的阶,且答案不超过。如输入数据1中,,置换为“4 1 5 2 3”,经计算其阶为6。
解题思路:
1.本题的核心是求给定排列的阶数,即找到最小的自然数,使得。
2.利用数论中排列可分解为不相交循环的性质。对于一个排列,每个元素都在某个循环节中。例如,若有排列,元素经过一系列变换最终回到,这就构成一个循环节。
3.先通过遍历排列中的每个元素,标记未访问过的元素,从这些元素出发,沿着排列的映射关系找到对应的循环节,并记录循环节的长度。
4.计算所有循环节长度的最小公倍数,这个最小公倍数就是排列的阶数。因为当每个循环节都回到初始状态时,整个排列就回到了恒等排列。
分析:
1.时间复杂度:遍历每个元素找到其所在循环节的时间复杂度为,其中是集合元素个数。计算循环节长度时,每个元素最多被访问一次。计算最小公倍数时,每次计算两个数的最小公倍数的时间复杂度近似为,总共最多计算次,所以计算最小公倍数的总时间复杂度也为。因此,整体时间复杂度为。
2.空间复杂度:使用一个布尔数组visited来标记元素是否被访问过,其大小为,用于存储循环节长度等的辅助变量空间复杂度较小,所以总的空间复杂度为。
实现步骤:
1.输入读取:从标准输入读取集合元素个数,以及排列的具体映射关系,即,并存储在数组p中。
2.初始化变量:定义一个布尔数组visited,初始化为false,用于标记元素是否已被访问;定义变量result,初始值为1,用于存储所有循环节长度的最小公倍数。
3.寻找循环节并计算长度:遍历从到的每个元素,如果该元素未被访问过,则从该元素出发,沿着排列的映射关系不断访问下一个元素,同时标记已访问的元素,直到回到起始元素,记录这个循环节的长度。
4.计算最小公倍数:对于每个找到的循环节长度,与当前的result计算最小公倍数,并更新result。
5.输出结果:最后输出result,即排列的阶数。
代码实现
#include <iostream> using namespace std; // 求两个数的最大公约数 int gcd(int a, int b) { while (b) { int temp = b; b = a % b; a = temp; } return a; } // 求两个数的最小公倍数 int lcm(int a, int b) { return a * b / gcd(a, b); } int main() { int n; cin >> n; int p[1001]; for (int i = 1; i <= n; i++) { cin >> p[i]; } int result = 1; bool visited[1001] = {false}; for (int i = 1; i <= n; i++) { if (!visited[i]) { int cycleLength = 0; int current = i; while (!visited[current]) { visited[current] = true; current = p[current]; cycleLength++; } result = lcm(result, cycleLength); } } cout << result << endl; return 0; }
代码说明:
1.函数定义:
gcd
函数采用辗转相除法计算两个数的最大公约数。通过不断用较小数对较大数取余,并更新两个数,直到余数为,此时的除数就是最大公约数。lcm
函数利用最大公约数计算两个数的最小公倍数,公式为。2.主函数部分:
(1)首先读取输入的集合元素个数和排列。
(2)初始化
result
为,visited
数组全为false
。(3)通过外层
for
循环遍历每个元素,若元素未被访问过,则进入内层while
循环寻找循环节。在循环节寻找过程中,标记访问过的元素并计算循环节长度cycleLength
。(4)找到一个循环节后,用
lcm
函数计算result
与cycleLength
的最小公倍数并更新result
。(5)最后输出
result
,即排列的阶数。
- 1
信息
- ID
- 1370
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 12
- 已通过
- 1
- 上传者