JS로 안풀려서 C++로 피보나치 수3를 열심히 깎아도 AC가 안뜬다.
문제의 코드
#include<stdio.h> int main() { long long n, f = 0, s = 1, mod = 1000000, i = 2; scanf("%lld", &n); while (i <= n) { long long temp = s; s = (f + s) % mod; f = temp; i++; } long long answer; printf("%d", n == 0 ? f : s); return 0; }
"피사노 주기"를 공부해야 풀 수 있는 문제란다.
피보나치 수열 F1, F2, F3, ... Fi가 존재할 때, n으로 나눈 값에 주기가 존재한다.
const getPisano = (n) => {
let prev = 0, curr = 1, res = 0;
for (let i 0; i < n * n; i++) {
let temp = prev;
prev = curr;
curr = (temp + curr) % n;
if (prev === 0 && curr === 1) {
res = i + 1;
break;
}
}
return res;
}
바로 문제를 풀어보자
피사노 주기를 구하는 함수를 작성하여 입력받은 값에 대하여 출력만 하면 되는 간단한 문제이다.
const [_, ...input] = require("fs") .readFileSync("/dev/stdin") .toString() .trim() .split('\n'); const getPisano = (n) => { let prev = 0, curr = 1, res = 0; for (let i = 0; i < n * n; i++) { let temp = prev; prev = curr; curr = (temp + curr) % n; if (prev === 0 && curr === 1) { res = i + 1; break; } } return res; } let answer = ''; for (let i of input) { const [num, m] = i.split(' ').map(Number); answer += `${num} ${getPisano(m)}\n` } console.log(answer);
피사노 주기 사용해서 풀어보자.
/* get pasino period */
const mod = 1000000;
const getPisano = (n) => {
let prev = 0, curr = 1, res = 0;
for (let i = 0; i < n * n; i++) {
let temp = prev;
prev = curr;
curr = (temp + curr) % n;
if (prev === 0 && curr === 1) {
res = i + 1;
break;
}
}
return res;
}
const pisano = getPisano(mod);
/* create fibo dp */
const input = BigInt(require("fs").readFileSync("/dev/stdin").toString().trim()) % BigInt(pisano);
let n = Number(input % BigInt(pisano));
const fibo = new Array(n + 1).fill(0);
fibo[0] = 0;
fibo[1] = 1;
for (let i = 2; i <= n; i++) {
fibo[i] = (fibo[i - 1] + fibo[i - 2]) % mod;
}
console.log(fibo[input] % mod);
n은 1,000,000,000,000,000,000보다 작거나 같은 자연수
입력값(input)이 굉장히 크다.
BigInt로 받고 바로 구했던 피사노주기로 나눠준 뒤, 피보나치 수열을 dp로 생성해준다.