[Python] 백준/BOJ 17626번: Four Squares (Silver 3)

2025. 2. 21. 11:00·Algorithm/백준 (BOJ)

💻 Problem

문제 보러 가기

 

라그랑주는 1770년에 모든 자연수는 넷 혹은 그 이하의 제곱수의 합으로 표현할 수 있다고 증명하였다. 어떤 자연수는 복수의 방법으로 표현된다. 예를 들면, 26은 5^2과 1 ^ 2의 합이다; 또한 4 ^ 2 + 3 ^ 2 + 1 ^ 2으로 표현할 수도 있다. 역사적으로 암산의 명수들에게 공통적으로 주어지는 문제가 바로 자연수를 넷 혹은 그 이하의 제곱수 합으로 나타내라는 것이었다. 1900년대 초반에 한 암산가가 15663 = 125 ^ 2 + 6 ^ 2 + 1 ^ 2 + 1 ^ 2라는 해를 구하는데 8초가 걸렸다는 보고가 있다. 좀 더 어려운 문제에 대해서는 56초가 걸렸다: 11339 = 105 ^ 2 + 15 ^ 2 + 8 ^ 2 + 5 ^ 2.

자연수 n이 주어질 때, n을 최소 개수의 제곱수 합으로 표현하는 컴퓨터 프로그램을 작성하시오.

 

💡 Approach

더 작은 제곱수의 합으로 더 큰 제곱수의 합을 만들 수 있으니 dp로 풀어야겠다는 생각은 들었다.

근데 점화식을 어떻게 만들어야 할지 모르겠어서 일단 다 적어보았다.. (틀린 방법이니 참고 ㄴㄴ)

  • dp[1] = 1 (1)
  • dp[2] = 2 (1 + 1)
  • dp[3] = 3 (1 + 1 + 1)
  • dp[4] = 1 (2^2)
  • dp[5] = 2 = dp[4] + 1 (2^2 + 1)
  • dp[6] = 3 = dp[5] + 1 (2^2 + 1 + 1)
  • dp[7] = 4 = dp[6] + 1 (2^2 + 1 + 1 + 1)
  • dp[8] = 2 = dp[4] + dp[4] (2^2 + 2^2)
  • dp[9] = 1 (3^2)
  • dp[10] = 2 = dp[9] + 1 (3^2 + 1)
  • dp[11] = 3 = dp[10] + 1 (3^2 + 1 + 1)
  • dp[12] = 3 = (2^2 + 2^2 + 2^2)
  • dp[13] = 2 = dp[9] + dp[4]
  • ...

위처럼 추측하며 점화식을 세워보니 아래 점화식이 나왔다.

dp[i] = min(dp[i], dp[j] + dp[i - j])

 

먼저 index를 value로 초기화한 dp 배열을 만들고 index가 제곱수인 칸은 1로 초기화했다.

세워둔 점화식으로 이중 반복문을 돌렸다.

import sys
input = sys.stdin.readline

n = int(input())
dp = [i for i in range(n + 1)]

for i in range(2, int(n ** 0.5) + 1):
    dp[i ** 2] = 1

for i in range(2, n + 1):
    for j in range(1, i // 2 + 1):
        dp[i] = min(dp[i], dp[j] + dp[i - j])

print(dp[-1])

근데 이러면 시간복잡도가 O(n^2)이 된다.

문제의 시간제한은 0.5초인데......

n의 최댓값은 5 * 10 ^ 4이다.

 

어떻게 최적화할 수 있을지 찾아봤다.

i를 만들 수 있는 제곱수를 기준으로 하여 여기에 i가 될 수 있도록 dp를 활용해 더한다.

  • dp[1] = 1 (1)
  • dp[2] = 2 (1 + 1)
  • dp[3] = 3 (1 + 1 + 1)
  • dp[4] = 1 (2^2)
  • dp[5] = 2 = dp[5 - 4] + 1 (1+ 2^2)
    • dp[1] + 1에서 + 1이 i(5)를 만들 수 있는 기준 제곱수(2^2)를 나타낸다.
  • dp[6] = 3 = dp[6 - 4] + 1 (1 + 1 + 2^2)
  • dp[7] = 4 = dp[7 - 4] + 1 (1 + 1 + 1 + 2^2)
  • dp[8] = 2 = dp[8 - 4] + 1 (2^2 + 2^2)
  • dp[9] = 1 (3^2)
  • dp[10] = 2 = dp[10 - 9] + 1 (1 + 3^2)
  • dp[11] = 3 = dp[11 - 9] + 1 (1 + 1 + 3^2)
  • dp[12] = 3 = dp[12 - 4] + 1 = (2^2 + 2^2 + 2^2)
  • dp[13] = 2 = dp[13 - 9] + 1 = (2^2 + 3^2)
  • ...

내가 처음에 접근한 방식이랑 어떻게 보면 좀 반대로(?) 접근해야 했다.

dp 어려웡 ㅠ

 

아무튼 다시 정리한 전개를 보면 점화식은 min(dp[i], dp[i - j * j] + 1)이 된다.

전체 로직은 다음과 같다.

  1. i를 만들 수 있는 제곱수를 기준으로 한다.
    1. 1부터 시작하여 하나씩 증가하는 j가 있을 때, j * j가 그 제곱수이다.
  2. i에서 제곱수를 뺀 dp 값과 1(제곱수 하나)을 더하면 i를 만들 수 있는 제곱수의 합 구성 개수이다.
    1. j 값을 늘리며 제곱수의 합 구성 개수의 최솟값을 갱신한다.

 

근데 모든 자연수가 넷 이하의 제곱수 합으로 표현할 수 있다는 게 신기하네😲

 

✏️ Solution

import sys
input = sys.stdin.readline

n = int(input())
dp = [i for i in range(n + 1)]

for i in range(4, n + 1):
    j = 1
    while j * j <= i:
        dp[i] = min(dp[i], dp[i - j * j] + 1)
        j += 1

print(dp[-1])

바깥 반복문을 n번만큼 반복하고, 안쪽 반복문을  √n번만큼 반복한다.

  • 시간복잡도: O(n√n)

n의 최댓값은 5 * 10^4이다.

대입하면 약 5√5 * 10^6 => 약 10^7이다.

시간제한 0.5초는 5 * 10^7이므로 아슬아슬하게 통과한다.

 

python으로 제출하면 시간초과이다.

pypy로 제출해야 통과한다.

반응형

'Algorithm > 백준 (BOJ)' 카테고리의 다른 글

[Python] 백준/BOJ 15810번: 풍선 공장 (Silver 2)  (0) 2025.02.23
[Python] 백준/BOJ 7662번: 이중 우선순위 큐 (Gold 4)  (0) 2025.02.22
[Python] 백준/BOJ 2667번: 단지번호붙이기 (Silver 1)  (0) 2025.02.20
[Python] 백준/BOJ 15965번: K번째 소수 (Silver 2)  (6) 2025.02.19
'Algorithm/백준 (BOJ)' 카테고리의 다른 글
  • [Python] 백준/BOJ 15810번: 풍선 공장 (Silver 2)
  • [Python] 백준/BOJ 7662번: 이중 우선순위 큐 (Gold 4)
  • [Python] 백준/BOJ 2667번: 단지번호붙이기 (Silver 1)
  • [Python] 백준/BOJ 15965번: K번째 소수 (Silver 2)
올콩
올콩
콩 심은 데 콩 난다
  • 올콩
    콩스토리
    올콩
  • 전체
    오늘
    어제
    • 분류 전체보기 (146) N
      • SSAFY (10)
      • Algorithm (72) N
        • 이론 (5)
        • 백준 (BOJ) (66) N
        • 프로그래머스 (1)
      • Language (9)
        • JavaScript (0)
        • TypeScript (0)
        • Java (9)
        • Python (0)
      • Library & Runtime (15)
        • React (13)
        • Node.js (2)
      • Framework (9)
        • 이론 (2)
        • Next.js (3)
        • Vue (4)
      • DevOps (3)
        • Git (3)
      • WEB (18)
        • HTML (9)
        • error (7)
        • etc (2)
      • Computer (5)
        • 자격증 (2)
        • tip (2)
        • etc (1)
      • CS (5)
        • Network (1)
        • Blockchain (4)
  • 블로그 메뉴

    • GitHub
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    강의
    SSAFY
    html5
    React
    bfs
    우선순위큐
    Java
    누적합
    딕셔너리
    백준
    재귀
    dfs
    vue
    렌더링최적화
    파이썬
    자바
    블록체인
    Error
    알고리즘
    github
    kakaomap
    SSAFYcial
    해시
    싸피
    오블완
    티스토리챌린지
    Next.js
    DP
    Algorithm
    카카오맵
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
올콩
[Python] 백준/BOJ 17626번: Four Squares (Silver 3)
상단으로

티스토리툴바