斐波那契数列对10007取余数,求余数的结果
- 题目:
问题描述
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。 -
思路:
一开始想的是不安着提示的方法来,是要通过求完斐波那契数列之后,才进行对10007取余数。结果类型给到了long,还是只通过了4到检测,后面就想着先输出前22个数字来,分别对每一个进行取余数,通过这些数列进行寻找规律,然后发现,第22个数字竟然是地20个数字+第21个数字,第23个数字也一样的道理,误以为又成为了另一个斐波那契数列:/* * 《=20时,不超过10007,不用取余数 * ==21 刚好超过10007,对其取余数 * 》=22 变成另一种规则,22=21+20,新的前两个相加的斐波那契数列 */ public void solve(int a){ if(a<3){//1 1直接返回 System.out.println(1); return; } else if(a<=20){//20以内,不用对10007进行取余 int [] arr=new int[a+1]; arr[1]=arr[2]=1; for(int i=3;i<arr.length;i++){ arr[i]=arr[i-1]+arr[i-2]; } System.out.println(arr[a]); } else if(a==21){//必须对21进行取余数 int [] arr=new int[a+1]; arr[1]=arr[2]=1; for(int i=3;i<arr.length;i++){ arr[i]=arr[i-1]+arr[i-2]; } System.out.println(arr[a]%10007); } else if(a>=22){//22就等于21+20的数,后面依次类推 long [] arr=new long[a+1]; arr[20]=6765; arr[21]=939; for(int i=22;i<arr.length;i++){ arr[i]=arr[i-1]+arr[i-2]; } System.out.println(arr[a]); } }
结果只通过了3个测试案例,居然比原先的还要少。极度郁闷。
唯有换另外一种想法,10007*x+i=y;怎么可以更简便呢??有时候,觉得灵感真是一瞬间就够了,拉了一泡屎;然后对100个数字进行输出斐波那契的值,以及它的余数,发现到后面的话,long的类型都不够存储,值变为负数了。
灵感一现,既然不能对最终的数进行对10007取余数,那么我就对每一个斐波那契数列进行取余数,这样的话,那么这个数字肯定不会》10007,所以就有一下的结果public void solve2(int a){ int [] arr=new int[a+1]; arr[1]=arr[2]=1; for(int i=3;i<arr.length;i++){ arr[i]=(arr[i-1]+arr[i-2])%10007;//对每一个斐波那契数列进行取余数 } System.out.println(arr[a]); /*for(int i=1;i<arr.length;i++){ System.out.print(arr[i]+" "); if(i%10==0) System.out.println(); }*/ }
- 总结:
- 找出规律要去验证,别误以为就是答案
- 将解决方法套到边界进行判断,是否结果正确