https://rebro.kr/97

 

PS를 위한 정수론 - (2) 유클리드, 확장 유클리드 호제법

[목차] 1. 유클리드 호제법 2. 확장 유클리드 호제법 3. 모듈러(modular) 연산에서의 곱셈의 역원 4. 예시 문제 1. 유클리드 호제법 유클리드 호제법은 정수론을 조금이라도 공부했다면, 혹은 공부하

rebro.kr

오랜만에 확장 유클리드가 필요해서 내용을 찾아봤는데, 위의 블로그의 코드를 찾게 되었다. 

블로그 설명에서는 해당 코드를 완벽히 설명한거 같진 않아서 정리해 본다. 

재귀적으로 작성하였는데, 그 부분을 설명해 보자면, 

 

\[gcd(a, b)=sb+t(a \% b)\]

를 만족한다고 두고, 

\[a\%b=a-(a/b)b\]

를 대입하면

\[gcd(a,b)=ta+\left\{s-t\left(a/b\right)\right\}b\]

코드에서 제시하는 식이 얻어짐을 확인할 수 있다.

이를 반복하도록 잘 구현한 것이 위의 블로그의 코드이다.

 

옛날에 KMO 정수론 공부할 때 이런 식으로 배운거 같은데 다 까먹어서 지금이라도 정리해 둔다. 

https://www.acmicpc.net/problem/5896

 

5896번: 효율적으로 소 사기

첫 번째 줄에 소 시장에 나온 소들의 마릿수 N(1 ≤ N ≤ 50,000), 농부 존이 가지고 있는 쿠폰의 개수 K(1 ≤ K ≤ N), 농부 존이 가지고 있는 돈 M(1 ≤ M ≤ 1014)이 주어진다. 다음 줄부터 Pi (1 ≤ Pi ≤

www.acmicpc.net

그리디한 접근법을 적용할 수 있는 문제이다. 간단히는 소의 숫자가 i+1인 경우의 최적해에서 고른 소가 i인 경우의 소를 항상 포함하기에 그리디한 접근이 가능하다고 보면 되겠다.

k개의 소를 구매할 때까지는, 쿠폰을 사용한 가격 중 낮은 순서부터 고르는 것이 최적임은 자명하다. 

그 이후에는 2가지 경우가 있는데, 하나는 남은 소들 중 쿠폰을 적용하지 않았을 때 가장 싼 소를 가져가는 것이다. 

또는 쿠폰을 사용하는 소를 추가해야 하는데, 쿠폰을 사용한 소들 중 하나를 쿠폰을 사용하지 않게 바꾸고 쿠폰을 사용하는 소를 추가해야 한다. (바꾸는 소를 고르는건 비용이 최소가 되도록 Priority Queue를 이용하자.)

이렇게 바꾸지 않을 경우, 보고 있는 소를 추가하는 것보다 지금 가지고 있는 소를 유지하면서 위의 경우를 사용하는 것이 낫기 때문이다. 다시 말해, 이미 쿠폰을 사용한 A라는 소가 있다고 하자. 시장에는 A보다 쿠폰가가 낮은 소가 없기에, A를 쿠폰을 사용하던 사용하지 않던 항상 데리고 있는 상태를 유지하는 게 최적이라는 것이다. 

이제 소의 숫자를 늘려 가며 2가지 경우 중 더 사용하는 돈이 적은 걸 선택하면 된다.

(쿠폰을 사용한 소의 가격과 사용하지 않은 소의 가격을 각각 정렬해 두면 시간 내에 해결할 수 있다.)

사용한 돈이 M을 초과하지 않을 때까지 소를 추가하는 걸 반복하면 문제를 해결할 수 있다. 

 

 

'알고리즘 > 백준' 카테고리의 다른 글

백준 3321 가장 큰 직사각형  (1) 2023.01.30
백준 20189 사탕 돌리기  (0) 2023.01.29
백준 10265 MT  (0) 2023.01.26
백준 9376 탈옥  (0) 2023.01.24
백준 3653 영화 수집  (0) 2023.01.23

https://www.acmicpc.net/problem/10265

 

10265번: MT

남규는 동기들과 엠티를 가기 위해 버스를 대절했다. 그런데 과사의 실수로 대절버스의 인원이 잘못되어 남규의 동기들을 모두 태울 수 없었다. 이 와중에 동기들은 화를 내며 다음과 같은

www.acmicpc.net

Solved.ac에서는 문제에 SCC태그를 달아놔서 쫄았는데, 풀어 보니 필요 없었다. P4라는 난이도도 부풀려진게 아닐까.

 

풀이로 넘어가서, 문제 상황만 보면 x_i를 데려가야 i를 데려갈 수 있기에, x_i에서 i로 간선을 연결하고 위상정렬을 하고 싶어진다. SCC가 있을 테니, 그걸 잘 처리하면 될 거 같다고 생각하게 된다.

이제 그래프의 형태를 관찰하면, In-degree가 하나니까 사이클이 하나 있고, 거기서 뻗어나가는 그래프가 만들어진다. 

그 예시로 문제의 두번째 TC에 대한 그림은 다음과 같다.

즉, 이 사이클 전체가 버스에 타면 해당 컴포넌트에서 나머지 사람들은 원하는 수만큼 버스에 태울 수 있고, 아니라면 이 컴포넌트의 사람은 아예 태울 수 없다.

그러면 해당 컴포넌트의 크기와, 해당 컴포넌트에서 사이클의 크기를 알면 문제를 해결할 수 있을 것이다. 컴포넌트의 크기는 Disjoint Set으로 구한다. 사이클의 크기는, 위에서 만든 그래프를 뒤집고 위상정렬을 하면 남는게 사이클이기 때문에 그 크기를 구할 수 있다.

(즉, 애초에  x_i에서 i로 간선을 연결할 필요 없이 i에서 x_i로 간선을 연결하면 된다! 필자의 사고 흐름을 정리한 것이기 때문에 위의 그래프가 나왔지만, 반대 그래프를 그려야 문제를 해결할 수 있다는 것이다. 물론 필자와 다른 방법(DFS 등)으로 사이클을 찾을 경우 위의 그래프를 활용하는 것이 더 좋을 때도 있겠다.)

 

이제 마지막으로 답을 구하기 위해서는 [n][k]짜리 일종의 knapsack DP를 하면 된다. i번째 컴포넌트까지 확인하고, j명을 태워야 할 때 태울 수 있는 사람의 수의 최대값을 저장하는 것이다. 

각각의 컴포넌트에 대해, 그 크기를 sz[i], 사이클 크기를 cyc[i]라 두면, 아래와 같은 점화식을 얻을 수 있다. i번째 컴포넌트의 사이클을 가져가거나, 가져가지 않을 수 있기 때문이다.

DP[i][j]=max(DP[i-1][j-cyc[i]]+sz[i], DP[i-1][j])

해당 DP를 수행하고, 마지막으로 데려갈 수 있는 사람의 수를 구할 때는 DP[n][j]의 최대값을 확인하면 답을 얻을 수 있다. 

'알고리즘 > 백준' 카테고리의 다른 글

백준 20189 사탕 돌리기  (0) 2023.01.29
백준 5896 효율적으로 소 사기  (0) 2023.01.28
백준 9376 탈옥  (0) 2023.01.24
백준 3653 영화 수집  (0) 2023.01.23
백준 3090 차이를 최소로  (0) 2023.01.05

https://www.acmicpc.net/problem/9376

 

9376번: 탈옥

상근이는 감옥에서 죄수 두 명을 탈옥시켜야 한다. 이 감옥은 1층짜리 건물이고, 상근이는 방금 평면도를 얻었다. 평면도에는 모든 벽과 문이 나타나있고, 탈옥시켜야 하는 죄수의 위치도 나타

www.acmicpc.net

먼저 1명이 탈출한다고 생각해보자. BFS를 통해 Flood Fill을 돌리는데, 지나온 문의 개수가 0개일때, 1개일때, ... 순서대로 방문하면 된다.

구현은 각각의 위치를 방문할 때 인접한 위치가 비어 있으면 현재 사용중인 큐에 넣고, 문이면 다음 큐에 넣어서 BFS를 돌리는 방식으로 하였다. 각각의 위치에 몇번째 큐에서 방문하였는지를 기록하면 된다. 필자는 귀찮아서 큐 10000개로 처리하였지만, 큐2개로 잘 처리해도 해결할 수 있을 것이다.

감옥의 테두리에서 몇번째 큐에서 방문하였는지가 탈옥 과정에서 연 문의 수가 된다. 이것의 최소값을 찾으면 1명짜리 문제는 해결된다.

 

이제 2명이 탈출하는 경우를 따져야 하는데, 2가지 경우를 생각해야 한다. 

1. 두 명이 따로 탈출하는 경우

2. 두 명이 탈출하는 중에 만나는 게 가능한 경우

 

1은 두 사람에 대해 위의 내용을 처리하고 두 값을 합하면 된다. 

 

2는 임의의 지점을 잡아 그 지점에서 만나서 바깥으로 나간다고 생각하면 된다. 이 부분을 해결하기 위해서는 감옥의 테두리 지점들을 보면서 빈 공간이면 첫번째 큐에, 문이면 두번째 큐에 넣고 시작하는 BFS를 하나 더 돌려서 총 3번의 BFS를 돌렸다. 그리고 각 지점을 보면서 그 지점이 만나는 지점이라고 생각해 3개의 BFS에서 얻어진 값을 더하면 되는 것이다. 

마지막으로 이 지점이 문인지 아닌지에 대해 처리를 해주자. 문이면 3번 카운트되므로 2를 빼야된다.

 

1번째 TC에 대해 해당 풀이를 적용한 그림은 다음과 같다. 

1번째 죄수에 대한 BFS
바깥에서 보는 BFS

표시한 지점에서 세 BFS의 값을 합한 값이 6이고, 해당 지점이 문이므로  2를 빼면 4가 얻어진다. 이게 최소라 해당 TC의 답은 4가 된다. 

'알고리즘 > 백준' 카테고리의 다른 글

백준 5896 효율적으로 소 사기  (0) 2023.01.28
백준 10265 MT  (0) 2023.01.26
백준 3653 영화 수집  (0) 2023.01.23
백준 3090 차이를 최소로  (0) 2023.01.05
백준 7469 K번째 수  (0) 2023.01.05

https://www.acmicpc.net/problem/3653

 

3653번: 영화 수집

각 테스트 케이스에 대해서 한 줄에 m개의 정수를 출력해야 한다. i번째 출력하는 수는 i번째로 영화를 볼 때 그 영화의 위에 있었던 DVD의 개수이다. 상근이는 매번 영화를 볼 때마다 본 영화 DVD

www.acmicpc.net

값을 삭제하고 앞에 삽입하는 걸 시간 내에 잘 해결해야 한다. 

m+n짜리 0/1 배열이 있다고 생각하면 문제를 쉽게 해결할 수 있다.

처음에는 i번째 영화를 m+i번째 자리에 놓아 값을 1으로 둔다.

그 영화를 k번째로 고르면 영화를 맨 앞으로 옮기는데, 원래 위치의 값을 0으로 바꾸고 m-k를 1로 바꾸면 된다. 이렇게 하면 문제에서 요구하는 순서를 가지게 됨을 알 수 있다.

각각의 쿼리에서 요구되는 값은 해당 0/1배열에서 처음부터 주어진 영화의 위치까지의 합이다. 이 합을 세그나 펜윅으로 관리하면 된다. 

각 영화의 위치에 접근하는걸 O(1)에 하도록 인덱스 배열을 만들어 관리하면 시간 내에 쿼리를 처리할 수 있다. 

'알고리즘 > 백준' 카테고리의 다른 글

백준 10265 MT  (0) 2023.01.26
백준 9376 탈옥  (0) 2023.01.24
백준 3090 차이를 최소로  (0) 2023.01.05
백준 7469 K번째 수  (0) 2023.01.05
백준 15972 물탱크  (0) 2023.01.05

https://www.acmicpc.net/problem/3090

 

3090번: 차이를 최소로

각각의 테스트 케이스에 대해서, 점수는 (100×(S+1)/(D+1))/(데이터 개수) 점이다. 이때, D는 출력한 수열에서 인접한 수의 차이의 최댓값, S는 정답이다. 즉, 출력한 수열이 정답인 경우 10점을 얻게

www.acmicpc.net

재밌는 파라메트릭 문제다. 

k를 매개변수로 잡고 차이가 k보다 작거나 같도록 만들 수 있는지에 대해 파라메트릭 서치를 하면 된다. 

그러면 k가 주어졌을 때 그 여부를 알아내는 알고리즘을 작성해야 하는데, 이는 다익스트라에서 아이디어를 구했다. 전부 우선순위 큐에 때려박고, 작은 지점부터 보면서 양쪽에 k보다 차이가 큰 지점이 있으면 그 지점을 낮춰 주고 Update하고 큐에 넣으면 된다. 각 과정에서 사용된 연산의 수를 합해서 T와 비교하면 된다. 이렇게 하면 다익스트라와 비슷한 방식으로 낮추는 과정에서 문제가 생기지 않는다. 

 

 

'알고리즘 > 백준' 카테고리의 다른 글

백준 9376 탈옥  (0) 2023.01.24
백준 3653 영화 수집  (0) 2023.01.23
백준 7469 K번째 수  (0) 2023.01.05
백준 15972 물탱크  (0) 2023.01.05
백준 22348 헬기 착륙장  (0) 2023.01.05

https://www.acmicpc.net/problem/7469

 

7469번: K번째 수

현정이는 자료 구조 프로젝트를 하고 있다. 다른 학생들은 프로젝트 주제로 스택, 큐와 같은 기본 자료 구조를 구현하는 주제를 선택했다. 하지만, 현정이는 새로운 자료 구조를 만들었다. 현정

www.acmicpc.net

i,j,k가 주어지면 배열 a[i...j]에서 k번째로 작은 수를 찾아내는 쿼리를 처리해야 한다.

구간 쿼리를 처리해야되니까 segment tree를 만들고 싶은데, 해당 쿼리를 처리하려면 merge sort tree를 만들면 된다.

머지 소트 트리를 만들면, 쿼리가 주어졌을 때 a[i...j]에서 임의의 수 x보다 작거나 같은 수의 개수를 알 수 있다. 각각의 구간에서 이분 탐색을 하면 된다.

그러면 파라메트릭을 하면서 k번째 수를 찾을 수 있음을 알 수 있다.

대충 시간복잡도는 O(QlogNlogNlogX)(X는 가능한 수의 개수(10^18)이하)이므로 시간 내에 문제를 풀 수 있다. 

'알고리즘 > 백준' 카테고리의 다른 글

백준 3653 영화 수집  (0) 2023.01.23
백준 3090 차이를 최소로  (0) 2023.01.05
백준 15972 물탱크  (0) 2023.01.05
백준 22348 헬기 착륙장  (0) 2023.01.05
백준 1315 RPG  (0) 2023.01.05

https://www.acmicpc.net/problem/15972

 

15972번: 물탱크

세로 길이가 N, 가로 길이가 M, 높이가 H인 물탱크가 있다. N, M, H는 모두 양의 정수이다. <그림 1>은 세로 길이가 2, 가로 길이가 3, 높이가 5인 물탱크 모양을 보여준다. <그림 1>에서 보듯이 물탱크

www.acmicpc.net

 

2018년 당시 서브태스크만 긁었던 문제. 당시에 생각한 아이디어 자체는 맞았기에 쉽게 AC를 받을 수 있었다. 

 

어느 한 칸의 물의 높이가 정해졌다고 생각하면, 그 칸보다 높은 인접한 칸을 따져 줄 때 크게 세 가지 경우가 있을 것이다. 두 칸 사이에 인접한 칸의 현재 상태보다 낮은 구멍이 없거나, 구멍이 두 칸의 높이 사이에 있거나, 구멍이 주어진 칸의 높이보다 낮은 경우이다. 첫번째 경우는 업데이트를 하지 않으면 되고, 두 번째 칸의 경우는 구멍의 높이로 업데이트 해주고, 세번째 경우는 주어진 높이로 업데이트하면 된다. 

 

높이가 낮은 순서대로 우선순위 큐에 넣어 따져 줄 칸을 정할 수 있고, 다익스트라랑 비슷한 아이디어이므로 이렇게 관리하면 된다는 증명도 비슷하게 할 수 있다. 

 

거리 대신 물의 높이를 기준으로 다익스트라를 구현하고, dis[i]+d[i][j]를 쓰는 대신 max(h[i], d[i][j])로 업데이트를 해 주면 쉽게 AC를 받을 수 있다. 

'알고리즘 > 백준' 카테고리의 다른 글

백준 3090 차이를 최소로  (0) 2023.01.05
백준 7469 K번째 수  (0) 2023.01.05
백준 22348 헬기 착륙장  (0) 2023.01.05
백준 1315 RPG  (0) 2023.01.05
백준 1178 간선 추가  (1) 2023.01.05

+ Recent posts