Java

[JAVA] 프로그래머스 멀리 뛰기

LimeCoding 2023. 8. 10. 22:22

프로그래머스 멀리 뛰기 문제를 잘 보면 재미있는 규칙이 나온다.

 

k가 1과 2로 이루어진 배열일 때 f(k)는 k 배열 속에 있는 1과 2를 나열하는 함수라고 해보자.

이때 동일한 숫자끼리 자리가 바뀌어도 하나의 경우의 수로 본다. 그러면

n = 1일 때, 

f([1]) = 1

 

n = 2일 때, 

f([2]) + f[1] = 2  

 

n = 3일 때,

f([1, 1, 1]) + f[1, 2] = 1 + 2 = 3

 

n = 4일 때,

f([1, 1, 1, 1]) + f[1,1, 2] + f[2, 2] = 1 + 3 + 1 = 5

 

n = 5일 때,

f([1, 1, 1, 1, 1]) + f[1,1, 1, 2] + f[1, 2, 2] = 1 + 4 + 3 = 8

 

n = 6일 때,

f([1, 1, 1, 1, 1, 1]) + f[1, 1, 1, 1, 2] + f[1, 1, 2, 2]  + f[2, 2, 2]  = 1 + 5 + 6 + 1 = 13

 

n = 7일 때,

f([1, 1, 1, 1, 1, 1, 1]) + f[1, 1, 1, 1, 1, 2] + f[1, 1, 1, 2, 2]  + f[1, 2, 2, 2]  = 1 + 6 + 10 + 4 = 21

 

이런 방식으로 증가한다.

이는 피보나치 수열과 동일한 방식으로 증가하기 때문에 n = k일 때 수는 n번째 피보나치 수열과 같다.

그런데 문제에서 요구하는 것은 k번 째 피보나치 수열을 1234567로 나눈 나머지이다. 이때 k번째까지 더한 후

mod 연산을 시도하면 long타입을 넘어가게 된다. 이를 방지하기 위해 모든 피보나치 수열에 해대 1234567로 나눈 후

더해준다. 원리는 다음과 같다.

a, b는 음이 아닌 정수이고 r1과 r2는 임의의 피보나치 수를 1234567로 나눈 나머지라고 했을 때 k-2 번째 피보나치 수열은 a * 1234567 + r1으로 나타낼 수 있고 k - 1번째 피보나치 수열은 b * 1234567 + r2로 나타낼 수 있다. 이때 우리가 구하고자 하는 k번 째 피보나치 수열은 다음과 같이 나타낼 수 있다.

즉, 계속해서 피보나치 수열을 더해 r1 + r2가 1234567을 넘어도 (a + b + 1) * 1234567 + r1 + r2 형태로 나타낼 수 있고 우리가 원하는 것은 피보나치 수를 1234567로 mod연산(% 연산)하여 (a + b) * 1234567을 없앤 r1 + r2 부분이기 때문에 피보나치 수를 모두 더하고 1234567로 나누는 것과 피보나치 수를 1234567로 나눈 나머지를 더해주는 것은 같은 결과가 나온다.

 

소스코드

class Solution {
    public long solution(int n) {
        
        long a = 0;
        long b = 1;
        long answer = 0;
        
        for(int i = 1; i <= n; i++) {
            answer = (a + b) % 1234567;
            a = b;
            b = answer;
        }
        
        return answer;
    }

'Java' 카테고리의 다른 글

[JAVA] assert 키워드  (0) 2024.04.28
[JAVA] Field와 Property  (1) 2023.10.02
[JAVA] 최대 공약수와 최소 공배수 구하기  (0) 2023.08.09
[JAVA] String과 char  (0) 2023.08.07
[JAVA] Comparator와 람다함수를 이용한 정렬  (0) 2023.08.03