蓝桥杯 入门训练 Fibonacci数列
Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。
当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。
说明:在本题中,答案是要求Fn除以10007的余数,因此我们只要能算出这个余数即可,而不需要先计算出Fn的准确值,再将计算的结果除以10007取余数,直接计算余数往往比先算出原数再取余简单。
1 #include<stdio.h> 2 #include<iostream> 3 #include<stack> 4 #include<vector> 5 #include<queue> 6 #include<deque> 7 #include<string> 8 9 using namespace std; 10 11 12 /* 入门训练 Fibonacci数列 */ 13 #define N 10007 14 int main() 15 { 16 long int n = 0; 17 cin >> n; 18 int a, b,cur; 19 cur = a = b = 1; 20 for (n -= 2; n >0; n--) 21 { 22 cur = (a+b)%N; 23 a = b; 24 b = cur; 25 } 26 cout << b; 27 28 return 0; 29 }
个人理解:
对于“说明:在本题中,答案是要求Fn除以10007的余数,因此我们只要能算出这个余数即可,而不需要先计算出Fn的准确值,再将计算的结果除以10007取余数,直接计算余数往往比先算出原数再取余简单。”这种官方OJ已经给出的说明来看:
1 我们应该是从这个余数方面的性质着手去找那个“不需要计算具体值而得出结果的方法”。
2 这种题目里面,我们肯定是从利用余数方面区去思考。
3 就两个数的合的余数,等于两个加数的余数的合再去 取余数。
4 考虑 上面那点的问题,我们可以这样想:
(1)余数这方面的数字问题,N(这题是10007)的整数倍的数值没关系。
(2)这题一定只有余数起作用。
(3)因为假设你正常算结果的话,到最终结果所有N的整数倍的数值都被减掉了。
(4)如果余数相加之后超过了一倍的N的话,只要要去剪掉(取余)一倍的N就ok了。
(5)综上,就有了 3 的结论。。
5 所以我们在这道题中,只关心每个步骤的余数内容就够了。
6 假如还在疑惑如果不是准确计算是不是还会影响结果的话我们还可以这么想:
(1)将一个数字分成(N*x(x>=0)+ K(余数))
(2)那么两个数字无论如果加减,都是N*x部分一定会被剪掉。
(3)同时K部分的相加若超出了N,则x+1,K - N即可,即上面的 3 结论
以上。