时间限制: 1.0s 内存限制: 512.0MB
【问题描述】
Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。
当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。
<此题禁止使用数组容器等数据结构>
【输入格式】
输入一行包含一个整数 n。
【输出格式】
输出一行,包含一个整数,表示满足条件的数的和。
【样例输入】
22
【样例输出】
7704
【评测用例规模与约定】
对于所有评测用例,1 ≤ n ≤ 1,000,000。
当n为35时,也就是计算第35个斐波那契数.
我用了三种方式来测试规律,第一种是普通的斐波那契数列.
第二种是有限变量来做斐波那契数列,我这里%9来测试.
第三种是用一个temp变量来做斐波那契数列求余问题.
Scanner input = new Scanner(System.in);int n = input.nextInt();int l1 = 1;int l2 = 1;// 先打印出正确的斐波那契数for(int i = 2;i < n;i++) {l2 = l1 + l2;l1 = l2 - l1;System.out.print(l2 + " ");}System.out.println();l1 = 1;l2 = 1;// 用有限变量做出这道题for(int i = 2;i < n;i++) {l2 = l1 + l2;l1 = l2 - l1;l2 %= 10007;System.out.print(l2 + " ");}System.out.println();l1 = 1;l2 = 1;// 用中间变量做出这道题for(int i = 2;i < n;i++) {int temp = l2;l2 = l1 + l2;l2 %= 10007;l1 = temp;System.out.print(l2 + " ");}// 输出(%9,留25个数):
// 可以发现,第一排的数%9之后,就是第二排和第三排的数
2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465
2 3 5 8 4 3 7 1 8 0 8 8 7 6 4 1 5 6 2 8 1 0 1 1 2 3 5 8 4 3 7 1 8
2 3 5 8 4 3 7 1 8 0 8 8 7 6 4 1 5 6 2 8 1 0 1 1 2 3 5 8 4 3 7 1 8
如果我们直接算出Fn,然后让Fn来除以10007的话,也可以,但是这个数太大了,需要用BigInteger来存,也很耗费时间,所以我们采用了这种方式.
接下来的一个问题是,为什么让每一个数%10007,结果却没变呢?
这是因为取余运算中存在定理:n%p = (a + b) % p = (a % p + b % p) % p.
这个过程用中间变量的这个做法来解释,更好说明一些.
我们最终求的那个斐波那契数Fn % p实际上就是(l1 + l2) % p,也就是(l1 % p + l2 % p) % p.
假设我们现在有三个数A B C
l1 为A,l2为B.A + B = C
temp等于此时的l2,也就是B % p.
然后l2 = A + B = C. 再除以10007求余. 此时l2 = C % p
而l1 = temp = B % p.
而假如再有一个D的话,
l2 = (l1 + l2) % p = (B % p + C % p ) % p
这个时候不就变成了(l1 % p + l2 % p) % p. 这种写法了吗?
l1 = 1;l2 = 1;// 用中间变量做出这道题for(int i = 2;i < n;i++) {int temp = l2;l2 = l1 + l2;l2 %= 10007;l1 = temp;System.out.print(l2 + " ");}