这个矩阵展示代码是对数的吗?

时间:2014-07-15 11:24:31

标签: c++ algorithm time-complexity matrix-multiplication fibonacci

我想以对数时间计算第n个斐波纳西数。所以,我写了这个函数

vector<vector<ll> > expon(ll k)
{
    if(k==1)
    {
        vector<vector<ll>> A({{1,1},{1,0}});
        return A;
    }
    auto A = expon(k/2);
    ll tmp[2][2] = {{0,0},{0,0}};
    for(int i=0;i<2;++i)
        for(int j=0;j<2;++j)
            for(int k=0;k<2;++k)
                tmp[i][j] += (A[i][k]*A[k][j])%modv;

    vector<vector<ll>> B({{tmp[0][0],tmp[0][1]},{tmp[1][0],tmp[1][1]}});
    if(k%2)
        return vector<vector<ll>>({{(tmp[0][0]+tmp[0][1])%modv,tmp[0][0]},{(tmp[1][0]+tmp[1][1])%modv,tmp[1][0]}});
    else
        return B;
}

但有些我觉得它花了太多时间。所以我想知道,它实际上是对数吗?我的意思是我的代码。

2 个答案:

答案 0 :(得分:2)

复杂性是对数的,但实施不是最理想的。您不需要递归,也不需要为矩阵的每个幂创建单独的向量实例。另一个注意事项 - 您有重复的变量k,这会导致警告,具体取决于编译器设置。

有一种方法可以检查给定的代码段是否为对数 - 衡量输入nn^2n^4所需的时间。如果复杂性是对数的,则每个测试应该花费大约两倍的前一个测试(同时请记住,测量可能在小持续时间内不准确)。

答案 1 :(得分:1)

你的算法是 O(k * logn),技术上是 O(logn)但是常量k可能很大,因为你在每次递归时创建向量分配所以它很慢。

尝试使用迭代解决方案: -

mat ans =[1,1,1,1];

while(k>0) {

  if(k&1) {

       ans = ans*a;
  }
  k=k>>1;
  a = a*a;
}

您可以注意到这是O(logn)并且不需要重新分配,而是需要两个2X2矩阵。