본문 바로가기

Tech

(580)
[BOJ] 1699번 - 제곱수의 합 문제설명 https://www.acmicpc.net/problem/1699 1699번: 제곱수의 합 어떤 자연수 N은 그보다 작거나 같은 제곱수들의 합으로 나타낼 수 있다. 예를 들어 11=32+12+12(3개 항)이다. 이런 표현방법은 여러 가지가 될 수 있는데, 11의 경우 11=22+22+12+12+12(5개 항)도 가능하다 www.acmicpc.net 사고과정 점화식을 발견하기가 어려웠다.. 제곱수를 어떻게 해야할지 몰랐다.. 풀이의 핵심적인 아이디어만 보고 소스코드는 직접 작성해보았다. 다행히 이건 통과했다. 문제풀이의 핵심 아이디어는 DP 테이블에는 입력되는 N을 제곱수 합으로 만들 수 있는 가장 최소항 개수를 넣어준다. 그리고 숫자를 $i$라고 할때, $j$는 $i$보다 작거나 같은 제곱수..
[BOJ] 1912번 - 연속합 문제설명 https://www.acmicpc.net/problem/1912 1912번: 연속합 첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다. www.acmicpc.net 사고과정 연속된 수열을 '몇 개'를 선택했을 때 가장 큰 합을 구하는 것이었다. 그래서 DP 테이블을 어떻게 작성해야 할까 매우 고민했다. 생각보다 너무 복잡하게 생각한 듯 했다..(풀이를 보니..) 주어진 데이터 범위가 최대 10만이였기 때문에 이중 loop만 돌아도 시간초과 에러가 발생할 게 뻔했다. 그래서 한 번의 loop로 해결해야 하는데.. 잘 떠오르지 않았다. 풀이를 보니 DP 테이블을..
[BOJ] 14002번 - 가장 증가하는 부분 수열 4 문제설명 https://www.acmicpc.net/problem/14002 14002번: 가장 긴 증가하는 부분 수열 4 수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이 www.acmicpc.net 사고과정 아무거나 수열 출력하는 부분에서 매우 고생했다.. 오히려 문제의 난이도가 여기에서 올라가는 것 같다.. 반례에 자꾸 걸려서 구글링을 했는데 구글링한 것 중에서도 간결한 코드를 찾기가 쉽지 않았다. 그러던 중 하나의 훌륭한 블로그 글을 발견하고! 해당 풀이를 참조했다!(감사합니다 :) 풀이(스스로 못..
[BOJ] 11053번 - 가장 긴 증가하는 부분 수열 문제설명 https://www.acmicpc.net/problem/11053 11053번: 가장 긴 증가하는 부분 수열 수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이 www.acmicpc.net 사고과정 이전에 이코테 문제에서 풀어본 병사 배치하기 문제를 통해서 LIS(가장 긴 증가하는 부분 수열) 알고리즘에 대해 배웠었다. git 팀 노트에 적어놓긴 했었지만 다시 회상할 겸 소스코드를 보지 않고 직접 머릿속으로 구현하려 했다. LIS 알고리즘 개념은 여기를 참고하자. 풀이 a = int(input()..
[BOJ] 2193번 - 이친수 문제설명 https://www.acmicpc.net/problem/2193 2193번: 이친수 0과 1로만 이루어진 수를 이진수라 한다. 이러한 이진수 중 특별한 성질을 갖는 것들이 있는데, 이들을 이친수(pinary number)라 한다. 이친수는 다음의 성질을 만족한다. 이친수는 0으로 시작하지 않 www.acmicpc.net 사고과정 경우의 수를 n = 7까지 나열해보고 패턴을 못찾는 듯 했으나..! 간신히 찾았다! 매우 간단한 점화식이었다. $dp[i] = dp[i-1] + dp[i-2]$ 처음에 인덱스 에러가 발생했는데, n = 1일 때의 조건을 처리해주어야 한다. DP에서는 입력이 1일 때 처리를 해주는 조건을 자주 붙이는 듯 하다. 1,2,3 더하기 문제랑 동일한 점화식이었다. 아쉽다고 한다..
[BOJ] 10844번 - 쉬운 계단 수 문제설명 https://www.acmicpc.net/problem/10844 10844번: 쉬운 계단 수 첫째 줄에 정답을 1,000,000,000으로 나눈 나머지를 출력한다. www.acmicpc.net 사고과정 1,2,3 더하기 5 유형과 비슷한 유형이였다. 이것도 2차원 리스트를 DP 테이블로 하는 것이었다. 이 때, DP 테이블에서 행($i$)는 글자 길이인 N을 의미하고 열($j$)는 맨 뒷자리에 나올 수 있는 숫자인 0부터 9까지이다. DP 테이블을 2차원으로 그리고 N = 3일 때까지 경우의 수를 세서 해보면 규칙을 파악할 수 있다. 바로 왼쪽 대각선 위와 오른쪽 대각선 위의 합이 DP[i][j] 값이라는 것! 이 때 j = 0 일 때는 왼쪽 대각선 위가 없으므로 오른쪽 대각선 위만 더하고..
[BOJ] 15990번 - 1, 2, 3 더하기 5 문제설명 https://www.acmicpc.net/problem/15990 15990번: 1, 2, 3 더하기 5 각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다. www.acmicpc.net 사고과정 저번 1,2,3 더하기 문제와 난이도가 매우 달랐던 것 같다.. DP 테이블을 1차원으로 정의하고 어떻게든 규칙을 찾아보려 했지만 실패했다. 핵심 풀이는 2차원으로 DP 테이블을 운영하는 것이었고 또 하나는 다이나믹 프로그래밍의 핵심인 "뒤의 입장에서 생각" 하기 였다. 어떤 뒤의 입장이냐.. 바로 1, 2, 3 합으로만 이루어진 것을 찾는 것이므로 특정한 수 n을 1, 2, 3의 합으로 만들 때, 그 연산에 사용된 마지막 피연산..
[BOJ] 16194번 - 카드 구매하기 2 문제설명 https://www.acmicpc.net/problem/16194 16194번: 카드 구매하기 2 첫째 줄에 민규가 구매하려고 하는 카드의 개수 N이 주어진다. (1 ≤ N ≤ 1,000) 둘째 줄에는 Pi가 P1부터 PN까지 순서대로 주어진다. (1 ≤ Pi ≤ 10,000) www.acmicpc.net 사고과정 카드 구매하기 문제랑 똑같은 문제이다. 단, 이번엔 최솟값인데, 점화식에서 max를 min으로만 바꾸어주면 된다. 카드 구매하기 문제에 대한 풀이는 여기를 참고하자. 풀이 n = int(input()) card = [0] + list(map(int, input().split())) dp = [0] * (n+1) dp[1] = card[1] dp[2] = min(card[2], car..
[BOJ] 11052번 - 카드 구매하기 문제설명 https://www.acmicpc.net/problem/11052 11052번: 카드 구매하기 첫째 줄에 민규가 구매하려고 하는 카드의 개수 N이 주어진다. (1 ≤ N ≤ 1,000) 둘째 줄에는 Pi가 P1부터 PN까지 순서대로 주어진다. (1 ≤ Pi ≤ 10,000) www.acmicpc.net 사고과정 경우의 수를 어느정도 나열해서 규칙을 발견하려 했는데 파악하지 못했다..뭔가 숨은 그림찾기 하는 느낌이다.. 바로 1번의 loop로 해결할 수 있지 않을까 했는데, n이 증가할 수록 비교하는 경우의 수가 많아짐에 따라 2중 루프를 사용했다. 예를 하나 들어보자. dp[1] 은 1번 카드 1개를 쓰는 방법만 있다. dp[2] 는 1번 카드를 2번 or 2번 카드를 1번 쓰는 방법만 있다...
[BOJ] 9095번 - 1, 2, 3 더하기 문제설명 https://www.acmicpc.net/problem/9095 9095번: 1, 2, 3 더하기 각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 출력한다. www.acmicpc.net 사고과정 경우의 수를 n = 5까지 나열해보고 '뒤의 입장'에서 생각해보려고 하는데 규칙을 찾지 못했다.. 풀이를 보니 매우 간단한 규칙이였다.. n이 4이상부터는 n-1, n-2, n-3일 때의 개수를 합해주면 된다.. 이런.. 매우 간단한 걸 캐치 못하다니..😢 점화식으로 나타내면 다음과 같다. $dp[i] = dp[i-1] + dp[i-2] + dp[i-3]$ 풀이(스스로 못 푼 풀이) for tc in range(int(input())): n = int(input()) dp =..
[BOJ] 11726번 - 2Xn 타일링 문제설명 https://www.acmicpc.net/problem/11726 11726번: 2×n 타일링 2×n 크기의 직사각형을 1×2, 2×1 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오. 아래 그림은 2×5 크기의 직사각형을 채운 한 가지 방법의 예이다. www.acmicpc.net 사고과정 예전에 풀어본 이코테의 바닥 공사랑 거의 유사한 유형이다. 단, 주어진 타일 종류가 다르다. 먼저 n = 2,3 될때까지 직접 그려보면서 다이나믹 프로그래밍의 "뒤의 입장에서 생각"하는 마인드로 접근해서 점화식을 잘 세울 수 있었다. 단, 몇 번 초반에 자꾸 에러를 받았는데, n = 1일 때 반례를 생각하지 못했다. n = 1 이게 되면 dp 테이블에서 2번 인덱스까지 정의했는데, 초기 array의 ..
[BOJ] 17103번 - 골드바흐 파티션 문제설명 https://www.acmicpc.net/problem/17103 17103번: 골드바흐 파티션 첫째 줄에 테스트 케이스의 개수 T (1 ≤ T ≤ 100)가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 N은 짝수이고, 2 < N ≤ 1,000,000을 만족한다. www.acmicpc.net 사고과정 골드바흐의 추측 문제와 비슷하게 풀이하면 된다. 단, a, b 쌍의 개수를 구하여야 하는데, 순서가 다른 a, b도 같은 것으로 여기므로 일종의 조합을 구해야 하는 문제이다. 어차피 순서가 다른 것도 같은 것으로 취급하기 때문에 n = a + b 경우를 돌 때, a가 n // 2 일 때까지만 돌면 된다! 참고로 처음에 array[2] = False로 해서 에라토스테네스 체에서 2의..
[BOJ] 1373번 - 2진수 8진수 문제설명 https://www.acmicpc.net/problem/1373 1373번: 2진수 8진수 첫째 줄에 2진수가 주어진다. 주어지는 수의 길이는 1,000,000을 넘지 않는다. www.acmicpc.net 사고과정 진수 변환방법은 아래와 같으며 10진수가 아닌 다른 진수에서 다른 진수로 바꾸려면 중간에 10진수 변환하는 과정을 꼭 거쳐야 한다. ex) 2진수 -> 8진수 = 2진수 -> 10진수 -> 8진수 진수에 따라 앞에 2글자 문자열이 붙는다 2진수: 0b -> 그래서 10진수에서 2진수로 바꾸려면 bin(10진수) 8진수: 0o -> 그래서 10진수에서 8진수로 바꾸려면 oct(10진수) 16진수: 0x -> 그래서 10진수에서 16진수로 바꾸려면 hex(10진수) 반대로 다른 진수에서..
[BOJ] 17087번 - 숨바꼭질 6 문제설명 https://www.acmicpc.net/problem/17087 17087번: 숨바꼭질 6 수빈이는 동생 N명과 숨바꼭질을 하고 있다. 수빈이는 현재 점 S에 있고, 동생은 A1, A2, ..., AN에 있다. 수빈이는 걸어서 이동을 할 수 있다. 수빈이의 위치가 X일때 걷는다면 1초 후에 X+D나 X-D로 이 www.acmicpc.net 사고과정 처음에 수빈이 위치인 S와 주어진 동생의 위치 간의 거리값을 구하고 이 거리값들 간의 최대공약수를 구하는 것 같다고 생각했었다. 그런데 갑자기 왜인지 모르게 그리디 방식으로 구현할 수 있을 것 같아 구현했는데 틀렸다는 판정이 나왔다.. 최대공약수를 활용한 풀이는 처음에 수빈이 위치와 주어진 동생의 위치 첫 번째 간의 최대공약수를 초기 answer로..
[BOJ] 9613번 - GCD 합 문제설명 https://www.acmicpc.net/problem/9613 9613번: GCD 합 첫째 줄에 테스트 케이스의 개수 t (1 ≤ t ≤ 100)이 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있다. 각 테스트 케이스는 수의 개수 n (1 < n ≤ 100)가 주어지고, 다음에는 n개의 수가 주어진 www.acmicpc.net 사고과정 처음에 입력으로 주어지는 문제를 대충 읽어서 좀 헤맸다.. 테스트 케이스 숫자 이후로 입력주어질 때 가장 맨 처음에 나오는 숫자는 다음에 나올 숫자의 개수를 의미했다.. 문제 좀 제대로 읽자 제에발! math 라이브러리와 모든 쌍을 구하기 위해 itertools의 조합 라이브러리를 활용 풀이 import math from itertools import c..
[BOJ] 2004번 - 조합 0의 개수 문제설명 https://www.acmicpc.net/problem/2004 2004번: 조합 0의 개수 첫째 줄에 정수 $n$, $m$ ($0 \le m \le n \le 2,000,000,000$, $n \ne 0$)이 들어온다. www.acmicpc.net 사고과정 주어진 데이터 범위가 20억이기 때문에 매우 큰 수다. 따라서 조합을 다 계산하는 것이 아닌 0의 개수만을 찾아야 함. 0개수는 2와 5의 개수로 알아낼 수 있다. 자세한 설명은 여기를 참고하자. 풀이(스스로 못 푼 풀이) import sys input = sys.stdin.readline n, k = map(int, input().split()) # (n, k) def count(n, num): cnt = 0 divnum = num wh..
[BOJ] 1676번 - 팩토리얼 0의 개수 문제설명 https://www.acmicpc.net/problem/1676 1676번: 팩토리얼 0의 개수 N!에서 뒤에서부터 처음 0이 아닌 숫자가 나올 때까지 0의 개수를 구하는 프로그램을 작성하시오. www.acmicpc.net 사고과정 문제를 보면 "N!에서 뒤에서부터 처음 0이 아닌 숫자가 나올 때까지 0의 개수"라고 되어 있는데, 처음에 이 말이 무슨말인지 이해를 잘 못했다. 질문에서 찾아보니 똑같은 질문을 한 게 있었고 보니까 이해할 수 있었다.(좀 더 부연설명이 되어 있으면 좋았을 듯 하다) 예를 들어, 10! = 3628800 이다. 이 때 362800에서 뒤에서부터 처음 0이 아닌 숫자가 나올 때까지 0의 개수니까 2개가 된다. for loop를 이용해서 인덱스를 감소시키는 방식으로 ..
[BOJ] 6588번 - 골드바흐의 추측 문제설명 https://www.acmicpc.net/problem/6588 6588번: 골드바흐의 추측 각 테스트 케이스에 대해서, n = a + b 형태로 출력한다. 이때, a와 b는 홀수 소수이다. 숫자와 연산자는 공백 하나로 구분되어져 있다. 만약, n을 만들 수 있는 방법이 여러 가지라면, b-a가 가장 큰 www.acmicpc.net 사고과정 우선 n = a + b 가 되는 경우의 수를 모두 살펴보지 않아도 된다. 이 때, b - a 가 가장 큰 것만 출력하면 되므로 a = (n // 2)가 될 때까지의 n = a + b 연산만 되는 경우를 확인하면 된다. 그리고 가장 먼저 n = a + b가 되는 조건이 만족했을 때가 b - a가 가장 클 때의 연산이다. 따라서 최초에 n = a + b가 되게..
[BOJ] 1978번 - 소수 찾기 문제설명 https://www.acmicpc.net/problem/1978 1978번: 소수 찾기 첫 줄에 수의 개수 N이 주어진다. N은 100이하이다. 다음으로 N개의 수가 주어지는데 수는 1,000 이하의 자연수이다. www.acmicpc.net 사고과정 다수의 소수를 찾는 알고리즘인 에라토스테네스의 체를 활용하면 된다. 주어지는 데이터의 최댓값이 1000이라고 했으므로 array 크기를 1001개로 초기화시켜준 후 한 번에 0부터 1000까지의 소수를 판별하고 난 후 주어진 nums를 하나씩 돌면서 해당 nums 인덱스에있는 array의 값이 True면 소수임을 의미한다.(0과 1은 소수가 아님을 잊지말자!) 또한 array 크기를 초기화시켜줄 때, 어차피 주어진 nums의 최댓값 + 1 의 길이..
[BOJ] 11656번 - 접미사 배열 문제설명 https://www.acmicpc.net/problem/11656 11656번: 접미사 배열 첫째 줄에 문자열 S가 주어진다. S는 알파벳 소문자로만 이루어져 있고, 길이는 1,000보다 작거나 같다. www.acmicpc.net 사고과정 문제는 쉽지만 기록하는 이유는 시간 복잡도에 익숙해지기 위함이다. 우선 문제에서는 문자열의 길이가 최대 1000이라고 했으므로 모든 접미사를 탐색하는 선형탐색 1000번 , 그리고 정렬시킬 때 파이썬 정렬 라이브러리를 이용했으므로 $(1000log1000)$이므로 10,000번, 마지막에 결과값을 출력할 때, 또 1000번 해서 총 12,000번의 연산을 수행한다. 파이썬에서는 1초에 천만번 연산을 수행하므로 시간초과 에러를 받지 않고 통과할 수 있다. 풀이..