N次幂矩阵乘法。更好的方法

时间:2012-07-06 19:52:32

标签: algorithm matrix complexity-theory

我有一个矩阵[2,2] [1,0]。我需要这个2 * 2矩阵的第n个多重复用。当我使用简单乘法时,我可以在O(n)或O(logn)中进行。 O(logn)代码:

int NUM(int n)
 {
  int F[2][2] = {{2,2},{1,0}};
  if(n == 0)
      return 0;
  power(F, n-1);
  return F[0][0];
 }

/* Optimized version of power() */
void power(int F[2][2], int n)
{
  if( n == 0 || n == 1)
  return;
  int M[2][2] = {{2,2},{1,0}};

 power(F, n/2);
  multiply(F, F);

 if( n%2 != 0 )
   multiply(F, M);
}

使用n值小的情况下工作得很好。但是如果n是10 ^ 9或更多的顺序,那么,long int甚至long long int将不起作用。所以,我相信这种方法看起来不像 很多帮助。

基本上我的问题是:数字变得非常大,甚至没有长期的int。然后我怎么能处理它。

当n为10 ^ 9时,有人可以建议我使用任何公式或算法来获得2 * 2矩阵[2,2] [1,0]的n次幂吗?

由于

2 个答案:

答案 0 :(得分:3)

这是家庭作业,还是仅仅是一项实施练习?如果你有选择,modulo可能更方便,基本上你在每次幂或乘法之后将矩阵模数为M,矩阵的各个条目永远不会超过(M-1)^ 2,但显然结果将是是一种模幂运算算法,因此与现有的算法不同。

因此,对于无符号长整数,模数最大可达65535左右,且无限指数。采用模数为矩阵的过程很简单:以每个数为模的数字输入。

请记住,无论如何,当指数增加时,这种模幂运算最终会进入一个循环(循环的大小取决于矩阵和模数的性质)。

代码看起来像这样(未经过测试,并不是特别优雅,几乎只是在每次乘法后插入矩阵模数):

/* Raises the matrix to the exponent n, modulo m. */
int NUM(int n, int m)
 {
  int F[2][2] = {{2,2},{1,0}};
  if(n == 0)
      return 0;
  power(F, n-1, m);
  return F[0][0];
 }

/* Takes a matrix modulo m. */
void modMatrix(int F[2][2], int m)
{
   F[0][0] = F[0][0] % m;
   F[0][1] = F[0][1] % m;
   F[1][0] = F[1][0] % m;
   F[1][1] = F[1][1] % m;
}

/* Optimized version of power() - raises a matrix F to the exponent n modulo modulus */
void power(int F[2][2], int n, int modulus)
{
  if( n == 0 || n == 1) return; // recursive termination condition

  int M[2][2] = {{2,2},{1,0}}; // original matrix for multiplication

 power(F, n/2, modulus); // raise the matrix to half the exponent
 modMatrix(multiply(F, F), modulus); // square the matrix to go the rest of the way

 if( n%2 != 0 ) modMatrix(multiply(F, M), modulus); // if the exponent is odd, multiply one last time
}

答案 1 :(得分:1)

由于它是一个2x2矩阵,一种可能的方法是将其扩展为一组 Pauli matrices和单位矩阵。然后使用Pauli矩阵的性质(square是一个单位矩阵等 - 参见链接页面)来计算N次幂,这不是纸笔练习的难度(见等式(2) )在上面的Wiki链接中)。