非常大的线性递归n

时间:2012-06-29 15:12:10

标签: java recurrence

我试图在SPOJ上解决这个问题(http://www.spoj.pl/problems/REC/)

F(n) = a*F(n-1) + b我们必须找到F(n) Mod (m)

0 <= a, b, n <=  10^100
       1 <= M <= 100000
F(0)=1

我正在尝试用JAVA中的BigInteger来解决它,但是如果我从0到n运行一个循环来获取TLE。我怎么能解决这个问题?任何人都可以给出一些暗示吗?不要发布解决方案。我想要提示如何有效地解决它。

2 个答案:

答案 0 :(得分:1)

注意,残基mod(m)的模式应该具有线性递归的重复模式,并且通过鸽子原理具有长度<= m。您只需要计算前m个条目,然后找出哪些条目将应用于F(n)以获得n的实际值。

它还有助于解决更简单的问题。让我们选择非常小的值,比如a = 2,b = 1,m = 5,n = 1000。

  • F(0)= 1
  • F(1)= 2 * F(0)+ 1 = 2 * 1 + 1 = 3 - > 3 Mod 5 = 3
  • F(2)= 2 * F(1)+ 1 = 2 * 3 + 1 = 7 - > 7 Mod 5 = 2
  • F(3)= 2 * F(2)+ 1 = 2 * 7 + 1 = 15 - > 15 Mod 5 = 0
  • F(4)= 2 * F(3)+ 1 = 2 * 15 + 1 = 31 - > 31 Mod 5 = 1
  • F(5)= 2 * F(4)+ 1 = 2 * 31 + 1 = 63-> 63 Mod 5 = 3

注意残留物是[1,3,2,0,1,3 ......],它们将永远重复。那么从这个例子中,你如何确定F(1000)Mod 5而没有一直循环到第1000个条目?

答案 1 :(得分:0)

首先,我会告诉你如何解决一个更简单的问题。假设b为零。然后你只需要计算一个 n mod M.而不是乘以n-1次,使用分而治之的技术:

// Requires n >= 0 and M > 0.
int modularPower(int a, int n, int M) {
    if (n == 0)
        return 1;
    int result = modularPower(a, n / 2, M);
    result = (result * result) % M;
    if (n % 2 != 0)
        result = (result * a) % M;
    return result;
}

所以你可以用 floor(n / 2)来计算 n ,然后将其平方,如果n是奇数,则再乘以a。

要解决您的问题,首先定义函数f(x)=(a x + b)(mod M)。你需要计算f n (1),这是对初始值1应用f n次。所以你可以像上一个问题一样使用分而治之。幸运的是,两个线性函数的组合也是线性的。您可以通过三个整数(两个常数和模数)表示线性函数。编写一个带有线性函数和指数的函数,并返回多次组合的函数。