https://www.acmicpc.net/problem/27877
27877번: 제곱수 덱 2
x의 최솟값을 998244353로 나눈 나머지를 출력한다. 만약 N장의 카드를 하나의 덱으로 합칠 수 없다면 -1을 출력한다.
www.acmicpc.net
문제가 상당히 간단하다.
관점을 조금 바꿔보자. 각 카드를 정점으로, 덱을 컴포넌트로 보면, 이 문제는 MST 문제로 환원될 수 있다. 가중치 간선의 곱에 대한 MST인데, 결과에 log를 씌운다 하면, 결국 곱셈이 덧셈으로 바뀌기에, 일반적인 MST 문제와 같다.
크루스칼 알고리즘을 생각해보자. 가중치가 적은 간선부터 선택하며 만약 그 가중치를 선택할 때 사이클이 생긴다면 선택하지 않는 식으로 작동하는 알고리즘이다.
예제어서 주어진 14에 대한 mst를 한번 만들어보면,

놀랍게도 가능한 모든 간선을 선택할 때 사이클이 한번도 생기지 않고 mst가 만들어진다.
또한 N < 14 일때 spanning tree가 만들어지지 않음을 알 수 있다.
N = 15일 때는 어떻게 될까? 15와 연결이 가능한 정점들은 1, 10, 21 .. 이 있고, 이 중 10을 선택하는것이 최소이다.
이런식으로 문제를 귀납적으로 풀 수 있다. 이미 만들어진 mst에서, 가장 가중치가 작은 간선을 선택하는 식으로 하면 된다. 이때 만들어질 수 있는 제곱수는 n + n - 1 보다 작거나 같은 제곱수만 가능하기에, 그런 제곱수 중 최소인 것을 선택하면 될 것이다.
이런식으로 풀다보면 이미 만들어진 mst에서 추가되는 정점과 다른 방식으로 선택하는 것이 더 좋은 선택지일수도 있지 않을까? 하는 생각이 들 수 있는데, 새로 추가되는 정점과 연결되는 간선이 항상 더 길다. 크루스칼 알고리즘에 의해서 이러한 간선을 선택해주면 안된다. 증명은 모르겠는데 대충 그럴거 같다.
식은 정리해보면 새로 추가되는 정점 N에 대하여 2N−⌊√2N−1⌋2가 나온다.
이제 dp처럼 하면 이 문제를 선형에 해결해 줄 수 있다.
그리고 식에서 중복이 생김을 이용하면, O(√N)에 풀 수 있다.
십덕사전지식이 아닌 다이아를 처음 풀어보는데, 상당히 재밌었다. 문제 자체가 그냥 재밌는듯..
'알고리즘' 카테고리의 다른 글
ps 일기 (NYPC 1519 본선 진출!) (0) | 2023.08.26 |
---|---|
코드포스 블루 달성 + 정올 얘기 + 잡설 (1) | 2023.07.27 |
백준 26937 Circular Barn python 풀이 (1) | 2023.04.28 |
백준 16136 준하의 정수론 과제 (Divmaster) (1) | 2023.04.11 |
우선순위 큐에서 원소를 삭제하는 테크닉 (3) | 2023.04.08 |