Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
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
Archives
Today
Total
관리 메뉴

LoCeL

[KOI'09] 섞기 수열 본문

PS

[KOI'09] 섞기 수열

LoCeL 2018. 11. 9. 11:03

 문제는 여기에서 확인 가능하다.


 permutation이 주어졌을때, 이것을 최소 몇 번 합성하면 identity permutation이 되는가를 묻는 문제로, disjoint cycle을 모두 찾아주고, 찾은 cycle들의 length의 최소공배수가 섞기 수열의 궤적이 된다.


 예를 들어서 섞기 수열이 $(3\;2\;5\;6\;1\;4)$로 주어져있다고 하면, 원래의 수열 $(1\;2\;3\;4\;5\;6)$에서 1은 3과 5를 거쳐서 1로 돌아오고, 2는 항상 제자리에, 4는 6을 거쳐서 다시 제자리로 돌아오게 된다. 따라서 주어진 섞기 수열의 disjoint cycle은 $(3\;5\;1)$, $(2)$, $(6\;4)$임을 알 수 있고, 첫번째 cycle은 3번마다, 세번째 cycle은 2번마다 제자리로 돌아오기 때문에, $lcm(3, 2) = 6$이 섞기 수열의 궤적이 된다.


 코드는 아래와 같다.


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
43
44
45
46
47
48
49
#include<bits/stdc++.h>
 
using namespace std;
 
int N, m[20001], c[20001];
 
vector<int> cycle;
 
int gcd(int a, int b) {
    int tmp, n;
    while(b != 0) {
        n = a%b;
        a = b;
        b = n;
    }
    return a;
}
 
int solve(vector<int> num) {
    int s = num.size(), ans = num[0], a = 0, h, l;
    for(int i = 1; i < s; i++) {
        a = num[i];
        h = max(ans, a);
        l = min(a, ans);
        ans = h * (l / gcd(h, l));
    }
    return ans;
}
 
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i = 1; i <= N; i++cin >> m[i];
    for(int i = 1; i <= N; i++) {
        if(c[i]) continue;
        c[i] = 1;
        int x = m[i], cnt = 1;
        while(x != i) {
            c[x] = 1;
            x = m[x];
            cnt++;
        }
        if(cnt != 1) cycle.push_back(cnt);
    }
    sort(cycle.begin(), cycle.end());
    cout << solve(cycle);
    return 0;
}
cs


'PS' 카테고리의 다른 글

[UCPC 2019] 이사 풀이  (0) 2019.08.01
[KOI'18] XCorr  (0) 2018.11.09
[BOJ 7347] 플립과 시프트  (0) 2018.11.09
[IOI'18] COMBO  (0) 2018.09.11
[UCPC'18 예선] 나무탈출  (0) 2018.08.14
Comments