※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 25399번 문제인 라그랑주님 수학에는 뺄셈도 있어요이다.
문제는 아래 링크를 확인하자.

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

 

25399번: 라그랑주님 수학에는 뺄셈도 있어요

라그랑주의 네 제곱수 정리란, 어떤 자연수 N을 최대 4개의 제곱수들의 합으로 나타낼 수 있다는 정리이다. 예를 들면, 30 = 12 + 22 + 32 + 42으로 나타낼 수 있고, 1217 = 342 + 62 + 52으로 나타낼 수 있다.

www.acmicpc.net

음의 정수의 경우 양의 정수를 구성하는 방법에서 부호를 바꿔 답을 구할 수 있으므로 양의 정수들을 제곱수로 구성하는 방법을 알아보자.

 

먼저 주어진 수 \(N\)이 한 개의 제곱수의 합으로 나타날 수 있는지를 확인하자. 이는 주어진 수가 제곱수인지를 확인하는 것과 같다.

 

다음으로 주어진 수가 두 개의 제곱수의 합(또는 차)으로 나타날 수 있는지를 확인하자.

주어진 수가 두 개의 제곱수의 합으로 나타낼 수 있는지의 여부는 투포인터를 이용해 \(O(\sqrt{N})\)에 구할 수 있다.

모든 3 이상의 홀수의 경우 \((n+1)^2-n^2=2n+1\)로부터 두 제곱수의 차로 구할 수 있음을 알 수 있다.

4의 배수의 경우 \((2n+1)^2-(2n-1)^2=4n\)로부터 두 제곱수의 차로 구할 수 있음을 알 수 있다.

그 외의 경우(짝수이지만 4의 배수가 아닌 경우)는 두 제곱수의 차로는 구할 수 없다. 모든 제곱수는 \(4n\) 또는 \(4n+1\)꼴임을 상기하자.

 

남은 수는 두 제곱수의 합으로 나타낼 수 없는, 4의 배수가 아닌 짝수이다.이 경우 아무 홀수 제곱수를 먼저 더한 다음 그렇게 만들어진 홀수를 두 제곱수의 차로 나타내는 것으로 세 정수를 이용해 표현할 수 있다. 이 과정에서, 먼저 더한 홀수 제곱수를 다른 두 수를 찾을 때 재사용하지 않도록 유의하자.

 

마지막으로 0을 1개 이상의 제곱수들로 구성해 문제를 해결하자.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

ll N; bool neg;
vector<ll> vec;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    cin >> N;
    
    if (N == 0) {
        cout << 3 << '\n' << "+ 5\n- 4\n- 3";
        return 0;
    }
    if (N == 2) {
        cout << 3 << '\n' << "+ 11\n+ 5\n- 12";
        return 0;
    }
    if (N == -2) {
        cout << 3 << '\n' << "- 11\n- 5\n+ 12";
        return 0;
    }
    
    if (N < 0) N *= -1, neg = 1;
    
    
    
    for (ll i = 1; i * i <= N; i++) {
        if (i * i == N) {
            if (neg) cout << 1 << '\n' << '-' << ' ' << i;
            else cout << 1 << '\n' << '+' << ' ' << i;
            return 0;
        }
        
        vec.emplace_back(i * i);
    }
    
    int L = 0, R = vec.size() - 1;
    while (L < R) {
        ll val = vec[L] + vec[R];
        if (val == N) {
            if (neg) cout << 2 << '\n' << '-' << ' ' << L + 1 << '\n' << '-' << ' ' << R + 1;
            else cout << 2 << '\n' << '+' << ' ' << L + 1 << '\n' << '+' << ' ' << R + 1;
            return 0;
        }
        
        if (val < N) L++;
        else R--;
    }
    
    if (N & 1) {
        ll x = N / 2 + 1, y = N / 2;
        if (neg) cout << 2 << '\n' << '-' << ' ' << x << '\n' << '+' << ' ' << y;
        else cout << 2 << '\n' << '+' << ' ' << x << '\n' << '-' << ' ' << y;
    }
    else if (N % 4 == 0){
        ll x = N / 4 + 1, y = N / 4 - 1;
        if (neg) cout << 2 << '\n' << '-' << ' ' << x << '\n' << '+' << ' ' << y;
        else cout << 2 << '\n' << '+' << ' ' << x << '\n' << '-' << ' ' << y;
    }
    else {
        N++;
        ll x = N / 2 + 1, y = N / 2;
        if (neg) cout << 3 << '\n' << '-' << ' ' << x << '\n' << '+' << ' ' << y << '\n' << '+' << ' ' << 1;
        else cout << 3 << '\n' << '+' << ' ' << x << '\n' << '-' << ' ' << y << '\n' << '-' << ' ' << 1;
    }
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 6192 // C++] Cow Pie Treasures  (0) 2024.01.12
[BOJ 6191 // C++] Cows on Skates  (0) 2024.01.11
[BOJ 2731 // C++] 1379와 세제곱  (1) 2024.01.09
[BOJ 8322 // C++] (K,N)-나이트  (1) 2024.01.08
[BOJ 9471 // C++] 피사노 주기  (0) 2024.01.07

+ Recent posts