Matrix multiplication (IV): analyze the problem, determine recursive, using fast power-solving matrix

      Rapid application matrix power operation can solve the problem recurrence. In practice, it is sometimes the subject does not directly give recursive, need to carefully analyze problems and identify recursive, and then use the matrix power operation quickly accelerate problem solving.

[Example 1] program reading comprehension.

      The following C language program:

#include <stdio.h>
int main()
{
     int n,m,f,i;
     while(scanf("%d%d",&n,&m)!=EOF)
     {
           f=0;
           for(i=1;i<=n;i++)
           {
                if (i&1)f=(f*2+1)%m;
                else f=f*2%m;
           }
           printf("%d\n",f);
     }
     return 0;
}

       Reading the above procedure, m and n in accordance with the input, to write the results of running the program. For example, input 310, output should be 5.

       However, due to the data range of n and m is given input 1 <= n, m <= 1000000000, and large amount of data in the test set, so if a given program is directly submitted will timeout. You write a program, according to the input n and m quickly solve the problem, in order to achieve a given program functions.

      (1) programming ideas.

      Given block is actually evaluated f (n)% m by an iterative manner. Is not considered remainder, find f (n) method of calculating.

      Analysis of a given program known, f (0) = 0, when n is odd, f (n) = 2 * f (n-1) +1; when n is an even number, f (n) = 2 * f ( n-1).

      The following further analysis, found not consider n parity of a unified recursive.

       When n is odd, f (n) = 2 * f (n-1) + 1, n-1 must be an even number, f (n-1) = 2 * f (n-2). therefore,

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

       When n is an even number, f (n) = 2 * f (n-1), n-1 always an odd number, f (n-1) = 2 * f (n-2) +1. therefore,

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

      Thus, to obtain uniform recursive formula: f (0) = 0, f (1) = 1, f (n) = 2 * f (n-2) + f (n-1) +1 (n> = 3).

      After determining the recurrence formula, the matrix P can be configured, for solving fast exponentiation.

       

      

 

      

 

       (2) source.

#include <stdio.h>
#include <string.h>
struct Matrix
{
      __int64 mat[4][4]; // 存储矩阵中各元素
};
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;
}
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,m;
      __int64 ans;
      Matrix p;
      while(scanf("%d%d" ,&n,&m)!=EOF)
      {
            memset(p.mat,0,sizeof(p.mat));
            p.mat[2][1]=2;
            p.mat[1][2]=p.mat[2][2]=1;
            p.mat[2][3]=p.mat[3][3]=1;
            if (n<3)
                 printf("%d\n",n%m);
           else
           {
                 p = quickMatPow (p, 3, n-2, m);
                 years = p.mat [2] [1]% m;
                 Yr = (+ p.mat years [2] [2] * 2)% m;
                 Yr = (+ p.mat years [2] [3])% m;
                 printf ( "% I64d \ n", year);
          }
      }
      Return 0;
}

[Example 2] The off all the lights.

       There are n lamps arranged in a row is initially fully lit, a first lamp press (change state after pressing). If the first k then all the lights off and the k + 1-th lights, the lights of the k + 2 can be press. At least ask how many steps you want to exterminate all the lights?

      For example, n = 2, requires 2 ho. The first two lights exterminate ho, ho exterminate second lights. when n = 3, 5 ho need. Ho exterminate first lights and the second lights ho exterminate 3, 3 1 ho lighting lights (lights unlit note 1, 2 can not be directly off lights), the fourth No. 2 ho exterminate light, 5 ho exterminate lights.

      (1) programming ideas. 

       Set F [n] and n represents full bright light becomes a minimum number of steps required for the full off, full-n may also represent extinguished lamp becomes minimum number of steps required for the full lighting. 
      1) in order to exterminate the last lamp, have to exterminate the front lights n-2 (the n-1 lights stay on), require several steps f [n-2] +1. 
      2) in order to exterminate the n-1 lights, n-2 have to let the second back light lamps, to n-2 of the back light lamps, have to let of n-3 lights back on. .. n-2 should i.e. before lights are turned back on, the number of required steps f [n-2]. 
      3) the front n-2 after the back light lamps, before leaving the n-1 lights are bright, i.e., the remaining task is to put the n-1 lights go out, the number of steps required f [n- 1]. 
      To sum up: f [n] = 2 * f [n-2] + f [n-1] + 1. (N> = 3) f [ 1] = 1, f [2] = 2.

      (2) source.

#include <stdio.h>
#include <string.h>
#define MOD 200907
struct Matrix
{
       __int64 mat[4][4]; // 存储矩阵中各元素
};
Matrix matMul(Matrix a ,Matrix b,int n)
{
      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]) % MOD;
      return c;
}
Matrix quickMatPow(Matrix a ,int n,int b) // 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); // c=c*a;
           a = matMul(a ,a ,n); // a=a*a
           b /= 2;
      }
      return c;
}
int main()
{
      int n;
      __int64 ans;
      Matrix p;
      while(scanf("%d" ,&n) && n!=0)
      {
           memset(p.mat,0,sizeof(p.mat));
           p.mat[1][2]=2;
           p.mat[1][1]=p.mat[1][3]=1;
           p.mat[2][1]=p.mat[3][3]=1;
           if (n<3)
               printf("%d\n",n%MOD);
           else
           {
                p = quickMatPow(p,3,n-2);
                ans=(p.mat[1][1]*2+p.mat[1][2]+p.mat[1][3])%MOD;
                printf("%I64d\n" ,ans);
           }
      }
      return 0;
}

Guess you like

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