[문제] 1 ~ 2n 까지 숫자가 적힌 카드가 각 1장씩 일렬로 순서대로 배치되어 있다.
이 카드들을 다음과 같은 방법으로 섞는다고 한다.
앞쪽 n 장의 카드를 A그룹, 뒤쪽 n 장의 카드를 B그룹으로 나누어
A1B1A2B2....AnBn 순으로 배열한다.
아래 그림은 n = 5일 때 카드를 섞는 과정을 보여주며, 총 6번 섞을 때 맨 처음의 순서로 돌아오는 것을 보여준다.

n의 범위가 1 ~ 100이라고 할 때, 카드들이 맨 처음의 순서대로 돌아오기 위해서 몇 번 섞어야 하는지를 조사한다고 하자.
1) 2 * (n - 1)번 섞었을 때 원래의 자기 자신으로 돌아올 수 있는 n들의 값은? (최초이든 2번째, 3번째이든 상관없다)
2) 2 * (n - 1)번 섞었을 때 최초로 원래의 자기 자신으로 돌아오는 n들의 값은?
즉, 1)은 2)의 모든 가짓수를 포함한다.
위 예시에서 보여준 n = 5일 때는 섞는 횟수가 6회, 12회, 18회... 등일 때 자기 자신으로 돌아오므로 1), 2) 모두 해당사항이 없다.
[알고리즘]
카드의 순서를 배열에 저장한다고 할 때,
[0] ~ [2n - 1] 각 인덱스에 위치한 카드들이 셔플 후 어느 위치로 이동하는지 살펴본다.

1) index <= n - 1일 때는
[index]에 있는 카드들이 [index + index] 위치로 이동한다.
예를 들어, [1]에 있는 카드는 [2]로, [2]에 있던 카드는 [4]로, [3]에 있던 카드는 [6]으로 이동한다. [n - 1]에 있던 카드는 [2n - 2]로 이동한다.
2) n <= index <= 2n - 1일 때는
[index]에 있는 카드들이 [index - (2n - 1 - index)] = [2*index - 2n + 1] 위치로 이동한다.
즉, [n]에 있던 카드는 [1]로, [n + 1]에 있던 카드는 [3]으로, [2n - 2]에 있던 카드는 [2n - 3]으로 이동한다.
위 규칙을 토대로, 2번 카드의 위치 변화를 관찰한다.
예를 들어, n = 5일 때, 2번 카드의 제일 처음 위치는 [1]이다.
위 규칙에 따라 2번 카드는 다음과 같이 움직인다.
[1] -> [2] -> [4] -> [8] -> [7] -> [5] -> [1]
즉, 6번 만에 다시 원래 위치인 [1]로 되돌아 온다.
위 내용을 바탕으로 코드를 작성하면 다음과 같다.
1) 2 * (n - 1) 번 섞었을 때, 원래의 자기 자신으로 돌아오는 n 찾기
#include <stdio.h>
#include <stdbool.h>
int main() {
int count = 0;
for (int n = 1; n <= 100; n++) {
int cnt = 0;
int index = 1;
bool revert;
while (cnt < 2 * (n - 1)) {
if (index <= n - 1) {
index += index;
}
else {
index -= (2 * n - 1 - index);
}
cnt++;
}
revert = index == 1;
if (revert) {
printf("n = %2d, cnt = %d\n", n, cnt);
count++;
}
}
printf("count = %d\n", count);
}
정답은 46개

2) 2*(n - 1)번 섞었을 때, 최초로 자기 자신으로 돌아오는 n 찾기
#include <stdio.h>
#include <stdbool.h>
int main() {
int count = 0;
for (int n = 1; n <= 100; n++) {
int index = 1;
int cnt = 0;
bool revert;
do {
if (index <= n - 1) {
index += index;
}
else {
index -= (2 * n - 1 - index);
}
revert = index == 1;
cnt++;
} while (!revert);
if (cnt == 2 * (n - 1)) {
printf("n = %2d, cnt = %d\n", n, cnt);
count++;
}
}
printf("count = %d\n", count);
}
정답은 22개

'프로그래밍 공부 > 알고리즘퍼즐68' 카테고리의 다른 글
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q51 과자로 장난하기 (첫번째 방법) (0) | 2026.07.02 |
|---|---|
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q50 동시에 끝나는 모래시계 (0) | 2026.07.01 |
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q48 급할수록 돌아가라 (0) | 2026.06.29 |
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q47 반전으로 만드는 엇갈리게 놓기 (0) | 2026.06.28 |
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q45 오직 하나뿐인 OX (0) | 2026.06.26 |