Matrix multiplication (C): According to the configuration of the matrix for fast exponentiation

      When the application fast exponentiation matrix, sometimes require suitable configuration. The following look at a classic on the subject of POJ.

【例1】Matrix Power Series (POJ 3233)

Description

Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak.

Input

The input contains exactly one test case. The first line of input contains three positive integers n (n ≤ 30), k (k ≤ 109) and m (m < 104). Then follow n lines each containing n nonnegative integers below 32,768, giving A’s elements in row-major order.

Output

Output the elements of S modulo m in the same way as A is given.

Sample Input

2 2 4
0 1
1 1
Sample Output

1 2
2 3

      (1) programming ideas.

      Subject means: input n * n matrix A, find S = A + A ^ 2 + A ^ 3 + ... + A ^ k of the result (two matrix positions, respectively corresponding to the sum is the sum), the data output mod m.

      Obviously can not be 2 ~ k-th power of each matrix are calculated, the time out.

      Can construct a 2n * 2n matrix P, using the method shown below,, block A is the original matrix, I is a unit matrix, O is a zero matrix.

    

      

        We found that P K +. 1  the upper right corner the one n * n block is required matrix A + A 2 + ... + A .

  So we construct a matrix P, and find it fast power matrix, a unit matrix minus the final result can be obtained.

      (2) source.

#include <stdio.h>
#include <string.h>
struct Matrix
{
      int mat[61][61]; // 存储矩阵中各元素
};
Matrix matMul(Matrix a ,Matrix b,int n,int m)
{
      Matrix c;
      memset(c.mat,0,sizeof(c.mat));
      int i,j,k;
      for (i = 1; i<=n ; i++)
          for (j=1 ;j<=n ; j++)
              for (k = 1 ;k<=n ;k++)
              {
                    c.mat[i][j]=(c.mat[i][j]+a.mat[i][k] * b.mat[k][j]) % m;
              }
      return c;
}
Matrix quickMatPow(Matrix a ,int n,int b,int m) // n阶矩阵a快速b次幂
{
      Matrix c;
      memset(c.mat ,0 ,sizeof(c.mat));
      int i;
      for (i = 1 ;i <= n ;i++)
      c.mat[i][i] = 1;
      while (b!=0)
      {
            if (b & 1)
                 c = matMul(c ,a ,n,m); // c=c*a;
            a = matMul(a ,a ,n,m); // a=a*a
            b /= 2;
      }
      return c;
}
int main()
{
      int n,k,m,i,j;
      Matrix p ;
      scanf("%d%d%d",&n,&k,&m);
      memset(p.mat,0,sizeof(p.mat));
      for (i=1;i<=n;i++)
          for (j=1;j<=n;j++)
              scanf("%d",&p.mat[i][j]);
      for (i=1;i<=n;i++)
      {
               p.mat[i][n+i]=1;        // 右上角的单位矩阵
               p.mat [n + i] [n + i] = 1; // matrix lower right corner
      }
      P = quickMatPow (P, * n-2, K +. 1, m);
      for (I =. 1; I <= n-; I ++)
      p.mat [I] [I + n-] -; // subtracting matrix
      for (I =. 1; I <= n-; I ++)
      {
            for (J = n-+. 1; J <= 2 n-*; J ++)
                 the printf ( "% D", (p.mat [I] [J] + m) m%);
            the printf ( "\ n-");
      }
      return 0;
}

      Since the P matrix configuration contains a large number of elements of 0, and therefore may be considered when the matrix multiplication be optimized, the optimization process is not performed if the zero element corresponding element calculation. The optimized matrix multiplication function is as follows:

Matrix matMul(Matrix a ,Matrix b,int n,int m)
{
      Matrix c;
      memset(c.mat,0,sizeof(c.mat));
      int i,j,k;
      for (k = 1; k<=n ; k++)
          for (i=1 ;i<=n ; i++)
             if (a.mat[i][k]!=0)
                 for (j = 1 ;j<=n ;j++)
                     c.mat[i][j] = (c.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % m;
      return c;
}

 

Guess you like

Origin www.cnblogs.com/cs-whut/p/11449050.html