[Beakjoon][Sliver][17626] For Squares
[문제 바로가기] : https://www.acmicpc.net/problem/17626
For Squares 문제
라그랑주는 1770년에 모든 자연수는 넷 혹은 그 이하의 제곱수의 합으로 표현할 수 있다고 증명하였다. 어떤 자연수는 복수의 방법으로 표현된다. 예를 들면, 26은 52과 12의 합이다; 또한 42 + 32 + 12으로 표현할 수도 있다. 역사적으로 암산의 명수들에게 공통적으로 주어지는 문제가 바로 자연수를 넷 혹은 그 이하의 제곱수 합으로 나타내라는 것이었다. 1900년대 초반에 한 암산가가 15663 = 1252 + 62 + 12 + 12라는 해를 구하는데 8초가 걸렸다는 보고가 있다. 좀 더 어려운 문제에 대해서는 56초가 걸렸다: 11339 = 1052 + 152 + 82 + 52.
자연수 n이 주어질 때, n을 최소 개수의 제곱수 합으로 표현하는 컴퓨터 프로그램을 작성하시오.입력은 표준입력을 사용한다. 입력은 자연수 n을 포함하는 한 줄로 구성된다. 여기서, 1 ≤ n ≤ 50,000이다.
출력은 표준출력을 사용한다. 합이 n과 같게 되는 제곱수들의 최소 개수를 한 줄에 출력한다.
문제 풀이
Dynamic Programming
문제이다.
먼저 문제에 따라 어떤 자연수를 제곱수의 합으로 나열해 본다.
i | Squares | Min | i | Squares | Min |
---|---|---|---|---|---|
1 | 1 | 11 | 3 | ||
2 | 2 | 12 | , | 3 | |
3 | 3 | 13 | , | 2 | |
4 | , | 1 | 14 | 3 | |
5 | 2 | 15 | 4 | ||
6 | 3 | 16 | , | 1 | |
7 | 4 | 17 | 2 | ||
8 | , | 2 | 18 | , | 2 |
9 | , | 1 | 19 | , | 3 |
10 | 2 | 20 | , , | 2 |
위의 표에서 알 수 있는 것은 i가 제곱이면 제곱수로 표현가능한 최소 개수는 1이란 것과 i보다 작은 제곱수로 빼면 이미 구해진 제곱수의 합들로 나머지가 구성된다는 것이다.
EX) i = 4인 경우
먼저 4보다 작은 경우는 어떻게 되나 생각해보자.
i이 1인 경우에는 외에는 존재하지 않는다. 따라서 이다.
i이 2인 경우, 외에는 존재하지 않는다.
i이 3인 경우, 외에는 존재하지 않는다.
의 초기값은 로 정의할 수 있다.
위에서 정의한 초기값은 최소가 아니므로 최소값을 구해준다.
i이 4이면, i보다 작거나 같은 제곱수는 , 이다.
으로 표현하면,
을 포함하면,
은 로 나타낼 수 있다.
N의 범위안의 제곱수로 을 대신하면 제곱수의 덧샘 수는 감소한다.
따라서 이다.
1을 더하는 이유는 2이상의 제곱수가 다른 제곱수를 대신하기 때문이다.
EX) i = 12인 경우
는 현재 밑의 표대로 저장되어 있다.
i | Squares | Min |
---|---|---|
1 | 1 | |
2 | 2 | |
3 | 3 | |
4 | 1 | |
5 | 2 | |
6 | 3 | |
7 | 4 | |
8 | 2 | |
9 | 1 | |
10 | 2 | |
11 | 3 |
i가 12이면, i보다 작거나 같은 제곱수는 , , 이다.
으로 표현하면,
을 포함하면,
을 포함하면,
이다.
초기값은 임으로,
이다.
이는 과 같다.
임으로, 이면,
이므로, 이다.
이는 와 같다.
으로 변경하고, 이면,
이므로, 이다.
문제 정답
C++ 17
#include <iostream>
#include <algorithm>
using namespace std;
int DP[50001];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
DP[1] = 1;
for (int i = 1; i <= N; i++)
{
DP[i] = DP[1] + DP[i - 1];
for (int j = 2; j * j <= i; j++)
{
DP[i] = min(DP[i], 1 + DP[i - j * j]);
}
}
cout << DP[N];
}
JAVA 11
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(bufferedReader.readLine());
int[] DP = new int[N + 1];
DP[0] = 0;
DP[1] = 1;
for(int i = 1; i <= N; i++) {
DP[i] = DP[i - 1] + DP[1];
for(int j = 2; j * j <= i; j++) {
DP[i] = Math.min(DP[i], DP[i - j * j] + 1);
}
}
System.out.println(DP[N]);
}
}
C# 9.0(.NET)
using System;
class Program
{
static void Main(string[] args)
{
int N = int.Parse(Console.ReadLine() ?? string.Empty);
int[] DP = new int[N + 1];
DP[1] = 1;
for (int i = 1; i <= N; i++)
{
DP[i] = DP[i - 1] + DP[1];
for (int j = 2; j * j <= i; j++)
{
DP[i] = Math.Min(DP[i], DP[i - j * j] + 1);
}
}
Console.WriteLine(DP[N]);
}
}
Author And Source
이 문제에 관하여([Beakjoon][Sliver][17626] For Squares), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@gloryday/BeakjoonSliver17626-For-Squares저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)