UVa 12792 - Shuffled Deck

contents

  1. 1. Problem
  2. 2. Sample Input
  3. 3. Sample Output
  4. 4. Solution

Problem

給定一種洗牌方式,請問重複多少次之後會復原到原本一開始的排列。

Sample Input

1
2
3
4
4
6
2
100002

Sample Output

1
2
3
4
4
3
2
100002

Solution

一道置換群的題目,將置換的方式找出,接著找一組一組循環置換集合,找到最小公倍數即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <algorithm>
using namespace std;
int A[1<<21], used[1<<21] = {};
int testcase = 0;
long long gcd(long long x, long long y) {
long long t;
while (x%y)
t = x, x = y, y = t%y;
return y;
}
int main() {
int n;
while (scanf("%d", &n) == 1) {
for (int i = 0; i < n; i++) {
if (i&1)
A[i] = i/2;
else
A[i] = i/2 + n/2;
}
testcase++;
long long lcm = 1;
for (int i = 0; i < n; i++) {
if (A[i] != i && used[i] != testcase) {
int ss = 0;
for (int j = i; used[j] != testcase; j = A[j])
used[j] = testcase, ss++;
lcm = lcm / gcd(lcm, ss) * ss;
}
}
printf("%d\n", lcm);
}
return 0;
}
/*
4
6
2
100002
*/