找到递归关系的第n项,给出前两个项,f(0)和f(1)

时间:2017-01-20 10:15:10

标签: java c++ c++11 recursion recurrence

f(n)= f(n-1)+ f(n-2)+ f(n-1)* f(n-2);

1< = n< = 10 ^ 9。初始条款 - > 1< = f(0),f(1)< = 10 ^ 9。

输出答案模10 ^ 9 + 7。

我发现的一般术语是, f(n)=(((1 + f(1))^ T(n))*((1 + f(0))^ T(n-1))) - 1; 这里T(n)是第n个斐波纳契数。

我使用矩阵求幂和模块化功率来解决问题,但它给出了TLE。

2 个答案:

答案 0 :(得分:1)

只要您还没有提供代码示例,我就会给您一个大致的想法。

就我个人而言,我不会使用递归,因为n可能很大,从而导致填充堆栈的低效和长计算并导致溢出。因此,使用数组更好地补充循环。

下一个提示是保持数字相对较小,每步计算模数。 (a+b+ab)%m等于(a%m + b%m + (a%m)*(b%m))%m(请参阅wiki),以便我们将数字保持在范围0..10^9

以下是解决方案的示例:

const unsigned int mod = 1e9+7;
std::vector<unsigned int> vec(n+1);    // prepare vector of needed size
                                       // size is n+1 because we start from 0 and you need vec[n]
vec[0] = 1;                            
vec[1] = 1e9;

unsigned long long int r1, r2;         // long long will prevent r1*r2 from overflowing
for (unsigned int i = 2; i <= n; ++i)
{
    r1 = vec[i-1] % mod;
    r2 = vec[i-2] % mod;
    vec[i] = (r1 + r2 + r1*r2) % mod;
}

std::cout << vec[n];

您使用[c ++]和[java]标记了您的问题。上面的代码在[c ++]中,我希望你能够在需要的时候移植它

答案 1 :(得分:1)

k = 1000000007是素数。因此a^b mod k相当于a^(b mod (k-1))

mod k,f(0)+1为2,f(1)+1为-6。

通过重复平方并选择正方形来相乘,可以有效地提升能力。

计算第n个Fibbonacci mod 1000000006很棘手(对于大n)。我不知道一个简单的封闭形式。

啊哈! Pisano时期是Fibbonnacci数字修改某些值重复的时期。 k被分解为素数2 * 500,000,003

简单地计算Pisano period的2和500000003.采用这两个素数的pisano时期的LCM来获得他们产品的pisano时期。我们可以使用它来减少n的模数值,然后再将其输入Fibbonnacci。

这给了我们一个有界的Fibbonnacci计算(希望是可以破坏的),让我们得到Fibbonnacci结果mod 1000000006,然后我们可以使用平方技术(mod 1000000007)将2和-6提升到那个幂,将它们加在一起减去1。

祝你好运计算皮萨诺时期。如果它是合理的(并且看起来很多),你应该能够获得十亿分之一的数字并在几分之一秒内解决。

现在,Pisano时期和Fibbonnacci的封闭形式是基于一些数论和数学。因此,我们可以尝试直接为此重复关系生成类似的数论/等结果,而不是通过您找到的身份。可以说,这会更难,但可能会得到一个更清晰的答案。