问题描述:
Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。
当n比较大,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。
输入格式:
输入包含一个整数n。
输出格式:
输出一行,包含一个整数,表示Fn除以10007的余数。
说明:在本题中,答案是要求Fn除以10007的余数,因此我们只要能算出这个余数即可,而不需要先计算出Fn的准确值,再将计算的结果除以10007取余数,直接计算余数往往比先算出原数再取余简单。
样例输入
10
样例输出
55
样例输入
22
样例输出
7704
数据规模与约定
1 <= n <= 1,000,000。
解决问题的核心是用了一个取余运算的公式: (a + b) % x = (a % x + b % x) % x
斐波那契数列的递推公式为 Fn = Fn-1 + Fn-2 ,现在要对Fn取余, 根据上述取余运算的公式,就等价于对(Fn-1 % x + Fn-2 % x)。 (要对Fn取余,就对Fn-1和Fn-2各自取余之和再取余。)
所以,只要把斐波那契数列的每一项做个转换就行了: 原来的数列,每一项是前两项之和,而现在变成每一项是前两项之和取余,就能解决问题了。(每一项都是个余数)
如“说明”中所讲,不用求出具体的斐波那契数到底是多少。如果把每一个斐波那契数都求出来然后在取余,一是时间不够,二是类型会溢出。
下面是转换前后的斐波那契数列的示例:
Nth | 1 | 2 | 3 | 4 | 5 | … | 18 | 19 | 20 | 21 | 22 | 23 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
原 | 1 | 1 | 2 | 3 | 5 | … | 2584 | 4181 | 6765 | 10946 | 17711 | 28657 |
转 | 1 | 1 | 2 | 3 | 5 | … | 2584 | 4181 | 6765 | 939 | 7704 | 8643 |
下面是代码: MyGithub
大段的注释可忽略
#include<stdio.h>
/*
// 求斐波那契数列的比递归快的方法,
// 但当n很大时,会溢出。
long fib(long n) {
long a = 1, b = 1;
if(n <= 2) {
return 1;
}
else {
long f;
long i;
for(i = 3;i <= n;i++) {
f = a + b;
a = b;
b = f;
}
return f;
}
}
*/
int main() {
long num, i;
scanf("%d", &num);
int a = 1, b = 1, f;
if(num<=2) {
printf("%d\n", 1);
}
else {
for(i=3;i<=num;i++) {
f = (a + b) % 10007; // 使从第三项起的每一项都变成余数
a = b;
b = f;
}
printf("%d\n", f);
}
return 0;
}
Email: [email protected]
GitHub: liberty1997