문제 해석
Finn은 요즘 수학공부에 빠져 있습니다. 수학 공부를 하던 Finn은 자연수 n을 연속한 자연수들로 표현 하는 방법이 여러개라는 사실을 알게 되었습니다. 예를들어 15는 다음과 같이 4가지로 표현 할 수 있습니다.
- 1 + 2 + 3 + 4 + 5 = 15
- 4 + 5 + 6 = 15
- 7 + 8 = 15
- 15 = 15
자연수 n이 매개변수로 주어질 때, 연속된 자연수들로 n을 표현하는 방법의 수를 return하는 solution를 완성해주세요.
제한사항
- n은 10,000 이하의 자연수 입니다
문제 풀이
[풀이 1번: 투포인터]
숫자 1만까지를 1부터 N까지 합이 1만일 때, 2부터 N까지 합이 1만일 때... 모든 경우를 찾는 코드를 처음에 생각해냈다.시간이 너무 길어질 것 같아서 꼼수를 생각해냈다.
- 처음 합이 N인 경우부터 투포인터를 이용하여 크다면 가장 작은 수를 버리고 작다면 이어지는 큰 수를 취한다.
- N이라는 숫자가 주어진다면 처음합은 N/2까지만 찾아내도 되는데 N/2을 a로 두었을 때
(a까지의 부분합은 a(a+1)/2일 것이고 이것이 N보다 큰 경우를 계산하면 (N-3)2/8 > 9/8로 N이 6일 때부터는 성립한다.) - 만약 2번에서 찾지 못한다면 시작점과 끝점을 0으로 시작한다.
[풀이 2번: 수학]
이 풀이를 처음보고 경악을 금치 못했다. 머리로 생각해내지 못하고 코드를 보고 알아낸 풀이다. 처음 생각한 사람 대단한 사람...
정말 증명하는데만 2시간 걸린 것 같은데 나는 수학과 머리는 아닌 것 같다 ㅎㅎ.
1. 자연수 k부터 m개의 연속된 숫자로 n을 나타낸다고 하면 아래와 같은 수식을 이용할 수 있다.
(m이 홀수나 짝수인 경우 모두 짝수와 홀수의 곱으로 나타나게 된다)
2. 여기서 2N이 홀수와 짝수의 곱으로 표현되려면 N의 홀수 약수의 갯수를 찾아내면 되는 문제가 된다.
코 드
투포인터 풀이
투포인터 풀이
#include <string>
#include <vector>
using namespace std;
int solution(int n) {
int answer = 1, ep = 0, sum = 0, sp = 1;
for (int i = 0 ; i < n/2; i++) {
if (i * (i + 1) / 2 >= n) {
ep = i;
sum = i * (i + 1) / 2;
break;
}
}
while (ep != n) {
if (sum == n) {
answer++;
sum -= sp;
sp++;
}
else if(sum > n) {
sum -= sp;
sp++;
}
else {
ep++;
sum += ep;
}
}
return answer;
}
수학적 풀이
#include <string>
#include <vector>
using namespace std;
int solution(int n) {
int answer = 0;
for (int i = 1 ; i <= n ; i+=2) {
if (n % i == 0) {
answer++;
}
}
return answer;
}
느낀점: 중등 수학이 이렇게 쓰일 줄 몰랐다... 코드를 효율적으로 짜려면 수학이나 정수론을 다시 공부해야하는가 싶은 하루였다.
링크: https://school.programmers.co.kr/learn/courses/30/lessons/12924#
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
'Problem Solving > 프로그래머스' 카테고리의 다른 글
[프로그래머스/Python] 행렬 테두리 회전하기 (0) | 2024.01.04 |
---|---|
[프로그래머스/Python] 수식 최대화 (0) | 2023.11.23 |
[프로그래머스/Python] 순위 검색 (0) | 2023.11.22 |
[프로그래머스/C++] 거리두기 확인하기 (0) | 2023.11.11 |
[프로그래머스/C++] 빛의 경로 사이클 (0) | 2023.11.02 |