본문 바로가기
Algorithm

[BaekJoon] 백준 알고리즘 1193번 / 분수찾기

by bkuk 2023. 2. 23.

문제

무한히 큰 배열에 다음과 같이 분수들이 적혀있다.

1/1 1/2 1/3 1/4 1/5
2/1 2/2 2/3 2/4
3/1 3/2 3/3
4/1 4/2
5/1

이와 같이 나열된 분수들을 1/1 → 1/2 → 2/1 → 3/1 → 2/2 → … 과 같은 지그재그 순서로 차례대로 1번, 2번, 3번, 4번, 5번, … 분수라고 하자.

X가 주어졌을 때, X번째 분수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 X(1 ≤ X ≤ 10,000,000)가 주어진다.

출력

첫째 줄에 분수를 출력한다.


접근방법

  • 급격한 난이도 증가로 인해서 어려움이 굉장히 많았다.
  • 이 문제를 풀기 위해서는 계차수열에 대한 지식이 어느정도 잡혀 있어야지 수월하게 풀 수 있다.
  • 계차수열이란 인접한 두 항에 대하여, 뒤 항에서 앞 항을 뺀 값을 계차(difference)라고 하는데, 원래 수열의 계차들을 항으로 하는 수열이라고 한다.
  • 말로는 굉장히 어렵게 느껴진다면, 아래 사진을 보자.

 

  • 아래와 같이 계차수열을 통해서 원수열의 일반항을 구할 수 있다.

(참고) 자연수의 거듭제곱의 합 공식 증명

더보기
  • 아래와 같이 시그마로 표현되어 있으면, 자연수의 거듭 제곱의 합 공식을 통해서 변환할 수 있다.
  • 이 공식은 등차수열의 합 공식을 유도할 때와 같은 원리로 유도할 수 있습니다. 수학자 가우스는 다음 자연수의 합 S = 1+2+3+ ... +n  을 순서를 뒤집어서 계산하는 아이디어를 제시했습니다.

 

  • 식의 양 변을 더하면 좌변은 2S가 되고, 우변의 각 항들을 더하면 (n+1)이 나옵니다.

 

  • 즉, (n+1)이 n개가 있는 상황이 발생합니다. 식을 정리하면 다음 공식을 얻을 수 있습니다.

 

  • 본 문제로 돌아와서, 아래와 같은 그림으로 분석할 수 있고 그룹으로 분류할 수 있다.

 

  • 이 문제를 풀기 위해서는 몇가지 확인을 해야한다.
1. 수를 입력 받았을 때, 그 수는 어느 그룹에 속하는지?

2. 그룹 내 몇번 째 위치에 속하는지?

3. 해당 그룹은 정방향인지 역방향인지?( 그룹 번호가 홀수인지 짝수인지?)

 

  • 따라서 어느 그룹에 속하는지 확인을 위해서 아래와 같이 일반항을 도출함.

  • 아래 코드를 보자.
BufferedReader br = new BufferedReader( new InputStreamReader(System.in) );
		
		// 1. 숫자를 입력받는다.
		int n = Integer.parseInt( br.readLine() );
		
		// 2. 그룹 번호, while문을 통해 자동 증가된다.
		int groupNumber = 1;
		
		// 3. 그룹 내 최대 번호, 초기값은 그룹번호 1일때를 기준
		int a = 1;
		
		// 4-1. 입력받은 값(n)이 그룹 내 최대 번호(a)보다 크다면 while문 반복
       		// 4-2. 입력받은 값은 무조건 그룹 내 최대번호와 같거나 작야아한다.
		while( n > a ) {
			groupNumber++;
			a = groupNumber + ( ( groupNumber - 1 ) * groupNumber / 2 );
		}
		
		// 5-1. 그룹 내 위치 찾는다.
       		// 5-2. 그룹번호는 그룹 내 존재하는 숫자를 의미하기도 한다.
        	// 5-3. 예) 2번 그룹은 그룹 내 2개 숫자, 3번 그룹은 그룹 내 3개의 숫자
		int position = groupNumber - ( a - n );
		
		// 6. 정방향인지 역방향인지 확인, 홀수면 정방향, 짝수면 역방향
		if( groupNumber % 2 == 0 ) {
			System.out.println( position + "/" +  ( (groupNumber + 1 ) - position ) );
		} else {
			System.out.println( ( (groupNumber + 1 ) - position ) + "/" + position );
		}