문제링크:  백준 9471 피사노 주기 

“ 피보나치 수열을 m으로 나눈 나머지가 P길이의 주기를 가진다.  “

 

 

피보나치 수열을 3으로 나누었을 때,  길이 8의 주기를 나타낸다. 
k(m)을 반복하는 부분수열의 길이라고 했을 때,  k(3) == 8 이다. 
주기의 길이가 p이면, n번째 피보나치 수를 mod으로 나눈 나머지는 n%p 번째 피보나치수를 mod로 나눈 나머지와 같다. 

주기를 이루는 숫자를 저장하는 벡터 v를 둔다고 생각해보자 (mod으로 나눈 나머지를 저장한다)

나누는 숫자 mod은 2 이상의 숫자가 주어진다

mod가 2일 때, 피보나치 수1을 2로 나누면 나머지가 1이다.  v[0] = 0, v[1] = 1, v[2] = 1 가 된다. 

 

주기의 앞 부분은 확실히 0, 1 순으로 시작하니까. 0, 1 이 연속으로 나오면 주기가 반복되는 지점임을 알 수 있다. 

그래서 벡터 v는 필요 없고 숫자 m1, m2만 필요하다. 


#include <bits/stdc++.h>
#define endp '\n';
using namespace std;

int p, n, m;

int pisano(int mod){

  int cnt = 0; // cnt 번째 피보나치 수
  int m1 = 0, m2 = 1; // 0과 1이 순서대로 나오면, 주기 발견.
  int tempsum = 0;

  while(1){
    tempsum = m1 + m2;
    m1 = m2;
    m2 = tempsum % mod;
    cnt++;
    if(m1 == 0 && m2 == 1) break;
  }

  return cnt;
}

int main(void){
  ios::sync_with_stdio(false);
  cin.tie(0);

  cin >> p;

  for(int i = 1; i <= p; i++){
    cin >> n >> m;
    cout << n << ' ' << pisano(m) << endp;
  }

  return 0;
}

 
 
 

참고
728x90

'알고리즘 > 백준' 카테고리의 다른 글

피보나치 수 백준 2747번 c++  (0) 2022.02.08
피보나치 수 3 백준 2749번 c++  (0) 2022.02.08
1로 만들기2 백준 12852 c++  (0) 2022.02.04
피보나치 수2 백준 2748 c++  (0) 2022.02.04
카드 백준 11652 c++  (0) 2022.02.04

+ Recent posts