网上看见关于蓝桥杯都是c++的,所以我自己分享一下java做蓝桥杯练习的感想与思路。
Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。
当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。(1 <= n <= 1,000,000。)
1,首先,我一看这题的结构,这不就是递归吗?于是:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner aScanner=new Scanner(System.in);
System.out.println(a(aScanner.nextInt())%10007);
}private static int a(int nextInt) {
if (nextInt==1||nextInt==2) return 1;
return a(nextInt-1)+a(nextInt-2);
}
}
测试了一下,输入20,完美运行。输入1000,诶?怎么这么久都没运行完?
然后我调试了一下,发现这样一个问题,当我输入值为4的时候,程序的运行方式是这样的:
看似好像没有什么问题,那么我们再试试5:
可以很明显看见红框的部分,当a(4)返回后,a(3)被再次执行,a(2)和a(1)也被执行。
如果我们再次输入6,可以想象a(4)将再次被执行,而a(4)下面的a(3),a(2)也会被执行。
我们很容易看出,按照这种方式运行程序,会导致很多重复的运算,而数字越大,重复的越多。
于是我用数组把每次运算的结果储存起来,比如
输入5,算出了a(3)的结果,那么把a(3)的结果存入数组,当a(4)返回后,再次运行a(3)的时候,我们直接取出数组中的a(3)的结果。这样就减少了很多次运算:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
int []a=new int [10000001];
a[1]=a[2]=1;
Scanner qScanner=new Scanner(System.in);
int q=qScanner.nextInt();
qScanner.close();
for (int i = 3; i <=q; i++) {
a[i]=a[i-1]+a[i-2];
}
System.out.println(a[q]%10007);
}
}
输入1000:2921 速度飞快;
输入10000:6072 小意思;
输入1000000:6730 没压力;
输入10000000:-2537!!! 什么情况;
初步判断应该是数据太大超出整形范围了,看见题目里有个温馨小提示,让我只要算出余数就行,不需要先计算出Fn的准确值,于是:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
int []a=new int [10000001];
a[1]=a[2]=1;
Scanner qScanner=new Scanner(System.in);
int q=qScanner.nextInt();
qScanner.close();
for (int i = 3; i <=q; i++) {
a[i]=(a[i-1]+a[i-2])%10007;
}
System.out.println(a[q]);
}
}
输入10000000:28 完美。
--------------------------------------------------------------------------------------------------------
作者后面想说的话
之后我发现,其实第二版输入100就已经是负数了,后面全是错的(捂脸)。
比完赛后感觉c++的竞争比Java要激烈很多,是因为没什么人用java写算法吗?网上也很难找到java的算法代码。
ps:蓝桥杯之后又学习了c++,终于知道堆内存是什么东西了!!多学习一门语言还是很有作用的(感慨)。