2024. 2. 5. 17:01ㆍPlatinum/Platinum III
난 세그먼트 트리를 모른다. 그런데 어느 날 balbad.ac solved.ac의 태그를 보다 보니 내가 세그먼트 트리 태그가 달린 문제를 푼 게 아닌가. 그것도 두 문제나. 이것은 기여가 잘못되었거나 아니면 비슷한 난이도의 다른 풀이가 있거나 둘 중 하나.
아니나 다를까 세그먼트 트리를 전혀 쓰지 않는 풀이법이 있었다. 대신 일정 이상의 수학 지식과 직관력이 요구되는 문제였다. 젠장 또 수학 문제야. 나는 수학 문제를 보고 말았어. 이제 나는 수학 문제를 풀어야만 해... 아무튼.
그럼 본격적으로 풀이에 돌입해 보자.
문제
상근이는 빵집에서 일한다. 상근이의 퇴근하기 전에 하는 마지막 업무는 빵을 사장이 원하는 순서대로 정렬하는 것이다.
최근에 상근이는 선영이에게 신기한 기술을 하나 배웠다. 이제 상근이는 기술을 이용해 서로 인접해 있는 빵 세 개를 동시에 주걱으로 던질 수 있다. 놀라운 점은 빵이 땅으로 내려올 때는 가장 오른쪽에 있던 빵이 가장 왼쪽으로 가고, 나머지 빵은 한 칸씩 오른쪽으로 이동하게 된다는 점이다. 즉, 빵의 순서가
이제 상근이가 퇴근할 시간이다. 상근이의 앞에는 지금 빵이 놓여져 있다. 지금 놓여져있는 빵의 순서와 사장이 원하는 순서가 주어졌을 때, 선영이에게 배운 기술만을 사용해서 빵을 정렬할 수 있는지 없는지를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 빵의 개수
예제 입력)
# 예제 입력 1
4
1 3 4 2
4 3 2 1
# 예제 입력 2
6
1 2 3 4 5 6
6 5 4 3 2 1
출력
만약, 상근이가 선영이에게 배운 기술만을 사용해서 사장이 원하는 순서를 만들 수 있으면 "Possible"을, 불가능하면 "Impossible"을 출력한다.
예제 출력)
# 예제 출력 1
Possible
# 예제 출력 2
Impossible
내 코드
def cyc_decomp(arr):
n = len(arr)
check = [False]*n
ans = []
for i in range(n):
if not check[i]:
ix = arr[i]; tmp = [i]; check[i] = True
while ix != i:
tmp.append(ix); check[ix] = True; ix = arr[ix]
ans.append(tmp)
return ans
N,arr1,arr2 = int(input()),[0],[0]
arr1.extend(list(map(int,input().split())))
arr2.extend(list(map(int,input().split())))
ans1,ans2 = cyc_decomp(arr1),cyc_decomp(arr2)
parity1,parity2 = 1,1
for i in ans1: parity1 *= pow(-1,len(i)+1)
for i in ans2: parity2 *= pow(-1,len(i)+1)
print(f'{"P" if parity1==parity2 else "Imp"}ossible')
일단 symmetric group
여기서
그리고 alternative group
로 증명이 됐으면 내가 이 풀이를 굳이 블로그로 썼겠는가. 위 풀이는 결론만 맞고 과정이 살짝 엉망이다.
모든 3-cycle
하지만 위에서 말한 바 있듯이, 확실히 결론은 맞다. 왜 그러는지 증명해 보자.
모든 원소가 다른 수열
그러면 '기술', 즉
심지어
이제 유사 정렬의 가능성에 대해서 증명해 보자. 우선
이제
그러면
따라서 귀납법에 의해서, 3 이상의 임의 길이의 수열은 '기술'로 유사 정렬을 시킬 수 있다.
이제 위 결과와 종합하면, 두 수열의 sign이 같으면 가능하며 다르면 불가능하다는 결과를 얻을 수 있다. 수열의 sign은 순열 사이클 분할을 한 뒤 각 사이클 길이
이로서 5000번의 풀이를 마친다.
