【问题标题】:nth term of series系列的第 n 项
【发布时间】:2012-07-02 09:19:14
【问题描述】:

我们要找到这个系列的第n个词http://oeis.org/A028859

n

答案应该是模 1000000007

我已经写了代码,但是当 n a 是巨大的数字时超过了时间限制。

#include<iostream>
using namespace std

int main()
{
    long long int n;
    cin>>n;

    long long int a,b,c;
    a=1;
    b=3;

    int i;
    for(i=3;i<=n;i++)
    {
        c=(2ll*(a+b))%1000000007;
        a=b;
        b=c; 
    }

    cout<<c;
}

【问题讨论】:

  • 有没有机会粘贴比这个更干净的代码示例,使用适当的缩进并避免过多的空白?
  • 这和动态规划有什么关系?
  • 两个简单的优化——你可以开始为循环中的每个迭代执行三个步骤,没有副本,执行 "c=2(a+b)..." "b=2(c +a)..." "a=2(b+c)...".然后,您也可以在第一步中在 c 上每个循环仅执行一次 mod。这应该是你的速度的两倍以上。
  • ?对不起老兄,你误解了DP的意思。 Dp 是关于存储计算值以便在将来的计算中使用它们,而不必再次计算它们。

标签: c++ algorithm series


【解决方案1】:

long long 不够用时,您可能想使用 bignum 库。例如GNU MP

【讨论】:

  • 但我们必须给出模1000000007的答案
  • long long int 不仅足够,而且我相信 unsigned long int 也足够,因为最大可能值为 4*10000007
【解决方案2】:

解决此类问题的标准技术是将其重写为矩阵乘法,然后使用exponentiation by squaring 有效地计算矩阵的幂。

在这种情况下:

a(n+2) = 2 a(n+1) + 2 a(n)
a(n+1) = a(n+1)

(a(n+2)) = (2  2) * ( a(n+1) )
(a(n+1))   (1  0)   ( a(n)   )

所以如果我们定义矩阵 A=[2,2 ; 1,0],那么您可以通过

计算第 n 项
[1,0] * A^(n-2) * [3;1]

所有这些操作都可以以 1000000007 为模完成,因此不需要大数库。

它需要 O(log(n)) 2*2 矩阵乘法来计算 A^N,所以总的来说这个方法是 O(log(n)),而你原来的方法是 O(n)。

编辑

Here 是一个很好的解释,也是这个方法的 C++ 实现。

【讨论】:

  • Here 我已经回答了一个类似的问题,但还利用了欧拉定理。 1000...07 是一个素数,因此您不必计算 A^N 但 A^(N % (p-1)) 就足够了。这样,该方法变为 O(1)(或 O(p),但 p 是常数)而不是 O(log(n))。
猜你喜欢
  • 2014-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-28
  • 2011-02-09
  • 1970-01-01
  • 2016-12-30
  • 1970-01-01
相关资源
最近更新 更多