PS(Java)/인프런 강의 문제

[PS] 인프런 강의 - Two Pointers, Sliding window, Math 5. 연속된 자연수의 합

UL :) 2022. 10. 24. 03:22

 

문제

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

 

풀이

연속 부분수열과 비슷하게 풀면된다.

풀이 2) N=15일 때 연속된 자연수의 합은 8까지만 체크하면 된다. 8+9=16이니까.

따라서 체크할 숫자 끝 값 = N/2 + 1 로 두고 푼다.

 

그런데 이것을 또 수학적으로 다르게 푸는 방식이 있다.

풀이 3) 15개를 연속된 자연수 cnt개로 분배할 경우를 구한다.

 

예를 들어 15를 2개로 분배할 경우

1. ○ + ○  여기에 1과 2를 할당한다.

2 그리고 15-1-2를 한 나머지를 2로 나눈다. 여기서 나누어 떨어지지 않으면 답이 아니다.

3. 그 값(6)을  ○ + ○ 여기에 분배하면 1+6, 2+6 으로 ○ + ○ = 7 + 8 = 15가 되므로 답이다. 즉 2번과정에서 나누어 떨어진다면 답으로 카운트하면된다.

 

cnt=2  n=12 (n-1=14 → n-=cnt. 14-2)  1(+6) + 2(+6) = 15

cnt=3 n=9 (n-=cnt. 12-3) 1(+3) + 2(+3) + 3(+3) = 15

cnt=4 n=5 (n-=cnt. 9-4) 15/4 != 0  답이 아님

cnt=5 n=0 (n-=cnt. 5-5) 1(+0) + 2(+0) + 3(+0) + 4(+0) + 5(+0) = 15

 

코드

1) 이중 for문이라서 n이 엄청 커진다면 시간 부족 에러가 뜰 것이다

1부터 합이 n이 될때까지 계속 더함
2부터 ..
3..
n-1 까지 반복

import java.util.Scanner;

public class Main {
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		
		int n = in.nextInt();
		int answer = 0;
		//2개 이상 연속된 자연수합으로 n을 표현하는 가짓수
		for(int i=1; i<n; i++) {
			int sum=i;
			for(int j=i+1; j<n; j++){
				sum+= j;
				if(sum==n) answer++;
			}
		}

		System.out.print(answer);
	}
}

 

2) 강사님 풀이

import java.util.Scanner;

public class Main {
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		
		int n = in.nextInt();
		int m = n/2 + 1; //1부터 체크할 숫자 개수
		int answer=0, sum=0;
	
		int[] arr = new int[n];
		for(int i=0; i<m; i++) {
			arr[i] = i+1; //0번 인덱스에 1이 들어가게끔
		}
		
		int lt=0;
		for(int rt=0; rt<m; rt++) {
			sum+= arr[rt];
			if(sum == n) answer++;
			while(sum >= n) {
				sum -= arr[lt++];
				if(sum == n) answer++;
			}
		}

		System.out.print(answer);
	}
}

 

3) 수학적 풀이

import java.util.Scanner;

public class Main {
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		
		int n = in.nextInt();
		int answer=0, cnt=1; //cnt는 연속된 자연수의 개수
		n--; //1빼준다.
		while(n>0) {
			cnt++;//2
			n-= cnt; //n-1-2-3.. 유기적으로 연결됨
			if(n%cnt == 0) answer++;
		}

		System.out.print(answer);
	}
}