일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 슬라이딩 윈도우
- 2357
- 정렬
- 13164
- DP
- 세그먼트 트리
- 이분 탐색
- 싸피
- 플로이드-워셜
- 문자열
- 구현
- 모던 JavaScript 튜토리얼
- 수학
- 해시 테이블
- 브루트포스
- 그리디
- 투 포인터
- BFS
- 정수론
- 맵
- 누적 합
- SSAFY
- 애드 혹
- 트리
- 에라토스테네스의 체
- DFS
- 그래프
- JavaScript
- boj
- Python
- Today
- Total
흙금이네 블로그
[BOJ] 17626 - Four Squares (Python, JavaScript) 본문
아이디어 #1
라그랑주에 의해 모든 자연수는 넷 혹은 그 이하의 제곱수의 합으로 표현할 수 있다고 증명되었으므로
7453번 - 합이 0인 네 정수처럼 두 제곱수를 더한 값들에서 투 포인터로 합이 n이 되는 네 제곱수를 찾는다.
풀이 #1 (Python)
딕셔너리 cnt_dict에 두 제곱수 합을 키로, 0이 아닌 제곱수의 개수를 값으로 저장한다.
입력 n이 50,000 이하로 주어지므로 제곱수의 제곱근은 223 이하로 설정하고, 0은 제곱수가 아닌 것으로 본다.
세트 numbers에 두 제곱수 합들을 저장한 후 numbers를 오름차순으로 정렬한 리스트로 대체한다.
투 포인터를 이용해 numbers에서 네 제곱수 합이 n인 경우를 찾아 최소 제곱수 개수를 갱신해 나간다.
n = int(input())
cnt_dict = dict()
numbers = set()
for i in range(224):
for j in range(224):
if i*i+j*j > n:
break
cnt_dict[i*i+j*j] = min(cnt_dict.get(i*i+j*j, 4), sum([i > 0, j > 0]))
numbers.add(i*i+j*j)
numbers = sorted(numbers)
s = 0
e = len(numbers)-1
res = 4
while s < e:
total = numbers[s]+numbers[e]
if total < n:
s += 1
elif total > n:
e -= 1
else:
res = min(res, cnt_dict.get(numbers[s], 4)+cnt_dict.get(numbers[e], 4))
s += 1
e -= 1
print(res)
아이디어 #2
다른 분의 코드를 참고해보니 라그랑주의 네 제곱수 정리를 이용하면 더 효율적으로 구현할 수 있었다.
n과 k가 정수일 때 4^n(8n+7)은 3개의 제곱수 합으로 나타낼 수 없지만, 나머지 정수들은 나타낼 수 있다.
따라서 입력으로 주어진 수를 제곱수와 두 제곱수 합에서 찾고, 나머지는 네 제곱수 정리로 찾는다.
풀이 #2 (Python)
제곱수를 리스트 numbers에 추가하면서 중간에 n을 찾으면 1을 출력하고 종료한다.
제곱수에서 n을 찾지 못하면 n에서 제곱수를 뺀 나머지를 numbers에서 찾고, 있으면 2를 출력하고 종료한다.
n에서 제곱수를 뺀 나머지도 찾지 못하면 n이 4로 나누어 떨어지는 동안 n을 4로 나눈 후,
그 나머지를 8로 나눈 나머지가 7이면 4, 그렇지 않으면 3을 출력한다.
n = int(input())
numbers = []
for i in range(1, 224):
if i*i == n:
print(1)
break
numbers.append(i*i)
else:
for num in numbers:
if n-num in numbers:
print(2)
break
else:
while n%4 == 0:
n //= 4
if n%8 == 7:
print(4)
else:
print(3)
풀이 #3 (JavaScript)
풀이 #2와 같은 방식으로 동작하며, 파이썬처럼 for-else문이 없어 결과값을 저장하는 res로 분기를 처리한다.
const fs = require('fs');
const input = fs.readFileSync('/dev/stdin').toString();
let n = Number(input);
let numbers = [];
let res = 0;
for (let i=0; i<224; i++) {
if (i*i === n) {
res = 1;
break
}
numbers.push(i*i);
}
if (res === 0) {
for (let num of numbers) {
if (numbers.includes(n-num)) {
res = 2;
break;
}
}
if (res === 0) {
while (n%4 === 0) n /= 4;
if (n%8 === 7) res = 4;
else res = 3;
}
}
console.log(res);
'알고리즘' 카테고리의 다른 글
[BOJ] 1025 - 제곱수 찾기 (Python, JavaScript) (0) | 2023.02.05 |
---|---|
[BOJ] 3687 - 성냥개비 (Python) (0) | 2023.02.02 |
[BOJ] 13506 - 카멜레온 부분 문자열 (Python) (0) | 2023.02.01 |
[BOJ] 2503 - 숫자 야구 (Python, JavaScript) (0) | 2023.02.01 |
[BOJ] 1135 - 뉴스 전하기 (Python) (0) | 2023.01.31 |