-
1699 - 제곱수의 합Programming/BackJoon 2023. 3. 17. 10:35728x90
1) 문제 링크
https://www.acmicpc.net/problem/1699
1699번: 제곱수의 합
어떤 자연수 N은 그보다 작거나 같은 제곱수들의 합으로 나타낼 수 있다. 예를 들어 11=32+12+12(3개 항)이다. 이런 표현방법은 여러 가지가 될 수 있는데, 11의 경우 11=22+22+12+12+12(5개 항)도 가능하다
www.acmicpc.net
2) 문제 설명
어떤 자연수를 제곱수로 나타낼 수 있다
ex ) 11 = 3^2 + 1^2 + 1^2 -> 3개로 가능
3) 문제 풀이
처음에는 받은 수 n 의 sqrt를 구해서 해볼 생각이었다. (수학 + 구현 문제인줄..)
예를 들어서 11이면
int(math.sqrt(11)) = 3
11 - 3^2 = 2
int(math.sqrt(2)) = 1
2 - 1^2 = 1
int(math.sqrt(2)) = 1
2 - 1^2 = 1
이렇게 해서 3번이 나온다
결과는 실패...
코드는 간결했다. 그러나 틀렸다.
더보기import math n = int(input()) cnt = 0 while n > 0: num = int(math.sqrt(n)) n -= num ** 2 cnt += 1 print(cnt)
뭔가 문제가 있다.
DP로 풀어봐야겠다
1 = 1^2
2 = 1^2 + 1^2
3 = 1^2 + 1^2 + 1^2
4 = 2^2
5 = 2^2 + 1^2
6 = 2^2 + 1^2 + 1^2
7 = 2^2 + 1^2 + 1^2 + 1^2
8 = 2^2 + 2^2
9 = 3^2
10 = 3^2 + 1^2
즉 제곱수가 나눠져 떨어지는 구간..1, 4, 9, 16에서 제곱수 값이 갱신되고
4 와 9 사이에는 1이 반복되는걸 볼 수 있다
이걸 점화식화하면
dp[i] = min(dp[i], dp[i - j**2] + 1)이다
+1을 하는 이유는 자기 자신을 포함해야기때문이다
sqrt를 사용해서 빈도수를 줄일 수 있다.
import math n = int(input()) dp = [x for x in range(n+1)] for i in range(1, n+1): for j in range(1, int(math.sqrt(i)+1)): dp[i] = min(dp[i], dp[i - (j**2)]+1) print(dp[n])
'Programming > BackJoon' 카테고리의 다른 글
11399 - ATM (0) 2023.03.21 2225 - 합분해 (0) 2023.03.20 2579 - 계단 오르기 (0) 2023.03.16 1912 - 연속합 (1) 2023.03.15 1966 - 프린터 큐 (1) 2023.03.15