Algorithm
[Java | Algorithm] 연속된 자연수의 합 - 수학적풀이
수짱수짱
2023. 4. 16. 20:51
lt와 rt로 2개의 pointer 개념을 이용한 문제풀이 방법은 이해가 됐지만 이런 수학적 풀이는 금방 까먹을게 뻔하기 때문에 (나 자신은 내가 잘 안다) 기록해두려 한다 ~.~
설명
N입력으로 양의 정수 N이 입력되면 2개 이상의 연속된 자연수의 합으로 정수 N을 표현하는 방법의 가짓수를 출력하는 프로그램을 작성하세요.
만약 N=15이면
7+8=15
4+5+6=15
1+2+3+4+5=15
와 같이 총 3가지의 경우가 존재한다.
입력
첫 번째 줄에 양의 정수 N(7<=N<1000)이 주어집니다.
출력
첫 줄에 총 경우수를 출력합니다.
예시 입력 1
15
예시 출력 1
3
해당 방법은 n을 연속된 숫자 합이 몇개로(자릿수로) 표현할 지에 중점을 둔다.
예를 들어 n이 15일 때 n을 2개의 연속된 합 숫자로 표현하기 위해선 자릿수(cnt)를 2로 두는 것이다. ( 15 = 7+8 )
진행 순서는 아래와 같다.
- 15(n) - 1 - 2 = 12
- 12 % 2(cnt) 가 0일 때 => 15는 2개의 연속된 숫자 합으로 표현 가능
- 1 + 2에 12/2의 몫 6을 각각 분배해준다면
- 7 + 8이 되고 이는 n값인 15와 같다
n이 15이고 n을 3개의 연속된 합 숫자로 표현할 때는 cnt를 3으로 맞춰두고 진행하면 된다. ( 15 = 4 + 5 + 6 )
- 15(n) - 1 - 2 - 3 = 9
- 9 % 3(cnt) == 0 이므로 answer++;
- 1 + 2 + 3에 9/3의 몫 3을 각각 분배해줄 때
- 4 + 5 + 6 = 15 로 n값인 15와 같아진다.
만약, n이 15이고 n을 4개의 연속된 합 숫자로 표현할 때는 cnt를 4로 맞춰두고 진행하면 된다. ( 15는 4개의 연속된 수로 표현할 수 없다 )
- 15(n) - 1 - 2 - 3 - 4 = 5
- 5 % 4(cnt) 가 0이 아닐 때 => 15는 4개의 연속된 숫자 합으로 표현 불가능
즉, 자릿수만큼 연속된 숫자(cnt가 3이면 1, 2, 3)를 n에서 뺀 값을 자릿수와 % 연산했을 때 결과값이 0일 때(= 나누어 떨어질 때) cnt만큼 연속된 숫자합으로 n을 표현할 수 있다는 것이다.
package inflearn.TwopointersANDSlidingwindow;
import java.util.Scanner;
// 3-5. 연속된 자연수의 합(two pointers) + (수학)
public class Twopointers3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] arr = new int[n/2+1]; // 연속된 자연수의 합중에 가장 큰 숫자는 n/2+1 이므로
for(int i=0; i<n/2+1; i++) arr[i] = i+1;
Twopointers3 twopointers3 = new Twopointers3();
System.out.println(twopointers3.solution(n, arr));
System.out.println(twopointers3.solution2(n));
}
// 수학적 방법
public int solution2(int n){
int answer = 0, cnt=1;
n -= cnt;
while(n>0){
cnt++; // 자릿수 증가
n -= cnt; // cnt가 연속된 자연수의갯수
if(n % cnt == 0) answer++; // 0%cnt도 0이므로 정답으로 카운팅된다.
}
return answer;
}
// two pointers 방법
public int solution(int n, int[] arr){
int answer = 0;
int lt = 0, sum = 0;
// lt와 rt로 연속된 수열을 구하는 문제
for(int rt=0; rt<arr.length; rt++){
sum += arr[rt];
while (sum > n){ // sum이 n보다 커진다면 lt값을 빼면서 lt를 증가시키며 n값과 작아질때 까지 반복 ( n값과 같으면 if문에 걸려서 answer count )
sum -= arr[lt++];
}
if(sum == n) answer++;
}
return answer;
}
}