模运算题

modular arithmetic problems

我遇到了一个简单算法的问题。问题如下:

问题描述 斐波那契数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1.

当n很大时,Fn也很大,现在我们想知道Fn超过10007的余数是多少。

输入格式

输入包含一个整数n。

输出格式

输出行包含一个整数,表示 Fn 除以 10007 的余数。

示例输入 10 示例输出

55

示例输入 22 示例输出

7704

数据大小和约定 1 <= n <= 1,000,000。

我的解决方案如下:

import java.util.Scanner;

/** * */ public class 主要 {

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int n = in.nextInt();
    System.out.println(recurrence(n));
    in.close();

}


/**
 *
 * @param n
 * @return
 */
public static int recurrence(int n) {
    int f1 = 1;
    int f2 = 1;
    int temp = f1;
    for (int i = 1; i <= n - 2; i++) {
        temp = (f1 + f2)%10007;
        f1 = f2;
        f2 = temp;
    }
    return temp;
}

}

上面的解是对的。但是我想说下面的解决方案有问题。

public static int recurrence(int n) {
    int f1 = 1;
    int f2 = 1;
    int temp = f1;
    for (int i = 1; i <= n - 2; i++) {
        f1 %= 10007;
        f2 %= 10007;
        temp = f1 + f2;
        f1 = f2;
        f2 = temp;
    }
    return temp;
}

temp = (f1+f2)%10007f1 %= 10007; f2 %= 10007; temp = f1 + f2;一样吗?

我的英语很差,希望你们能明白我的意思。谢谢!

重写取模结果有一定的属性。 Wikipedia 展示了其中的一些。与此处相关的是:

(a + b) % n = ((a % n) + (b % n)) % n

所以如果你改变

Fn = Fn-1 + Fn-2

Fn = (Fn-1 + Fn-2) % 10007

你得到你想要的,因为 Fn-1 和 Fn-2 已经有了 % 10007应用。

static int fibMod(int n, int mod) {
    if (n < 0 || mod < 2)
        throw new IllegalArgumentException();
    if (n <= 1)
        return n;
    int prev = 1, fib = 1;
    for (int i = 3; i <= n; i++)
        fib = (prev + (prev = fib)) % mod;
    return fib;
}

测试

System.out.println(fibMod(10, 10007));
System.out.println(fibMod(22, 10007));
System.out.println(fibMod(1_000_000, 10007));

输出

55
7704
114