Matrix Fast Power (Standard Template)

Topic description
Given an n*n matrix A, find A^k

Input and output format
Input format:
the first line, n, k

Rows 2 to n+1, each row has n numbers, and the jth number in row i+1 represents the element in row i and column j of the matrix

Output format:
output A^k

A total of n rows, each row has n numbers, the i-th row and the j-th number represent the elements of the i-th row and the j-th column of the matrix, each element modulo 10^9+7

Input and output example
Input example #1:

2 1
1 1
1 1

Sample output #1:

1 1
1 1

Description
n<=100, k<=10^12, |Matrix Elements|<=1000 Algorithm: Matrix Fast Power

This question is the method of using the fast power of the matrix. The following code is also a standard template code, so there is no need to change anything.
Of course, such a standard code is definitely a template code.
Matrix algorithm
The size of matrix A is n×m, and the size of B is n×k, set C=A×B then C{i,j}= ∑ k = 1 n \sum_{k=1}^nk=1nA{i,p} ×B{p,j}

Example:
Matrix multiplication satisfies the associative law: (AB) C = A (BC)
There is a special matrix: the identity matrix, whose elements on the diagonal from the upper left corner to the lower right corner are all 1, and all other elements are 0 . It is equivalent to 1 in number multiplication in matrix multiplication, i.e. any matrix multiplication is equal to itself.

The above is the basic knowledge necessary to play the matrix fast power.
Code Implementation
Now that we understand matrix multiplication, we can use functions to simulate matrix multiplication.

Mat Mul(Mat x,Mat y)
{
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
        c.m[i][j]=0;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
        for(int k=1;k<=n;k++)
        {
            c.m[i][j]=c.m[i][j]%mod+x.m[i][k]*y.m[k][j]%mod;
          }
    return c; 
}

Because matrix multiplication satisfies the associative law, fast exponentiation is completely applicable to matrices. The matrix fast exponentiation is almost the same as the ordinary fast exponentiation. The difference is that the "*" sign is changed to the Mul function.

Mat pow(Mat x,ll y)
{
Mat ans=e;
while(y)
{
    if(y&1)
     ans=Mul(ans,x);  
    x=Mul(x,x);
    y>>=1;
}
return ans;
}

After knowing this, this question can basically be AC.

Finally, pay attention to open long long, otherwise it will explode.

AC code:

#include<iostream>
#include<cstring>
#define mod 1000000007
#define ll long long
using namespace std;
struct Mat{
    ll m[101][101];
};//结构体存矩阵 
Mat a,e;//a是输入的矩阵,e是单位矩阵 
ll n,p;
Mat Mul(Mat x,Mat y){ //矩阵乘 
    Mat c;
    for(int i = 1;i <= n;i++)
      for(int j = 1;j <= n;j++)
        c.m[i][j] = 0;
    for(int i = 1;i <= n;i++)
      for(int j = 1;j <= n;j++)
        for(int k = 1;k <= n;k++){
            c.m[i][j] = c.m[i][j] % mod + x.m[i][k] * y.m[k][j] % mod;
          }
    return c; 
}
Mat pow(Mat x,ll y){ //矩阵快速幂 
    Mat ans = e;
    while(y){
        if(y&1){
        	ans = Mul(ans,x);         	
        }
        x = Mul(x,x);
        y >>= 1;
    }
    return ans;
}
int main(){
    //输入 
    cin >> n >> p;
    for(int i = 1;i <= n;i++){
    	for(int j = 1;j <= n;j++){
    		cin >> a.m[i][j];
    	}    	
    } 
     //算法核心     
    for(int i = 1;i <= n;i++){
        e.m[i][i] = 1;       	
    }
 
    Mat ans = pow(a,p);
    //输出 
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= n;j++){
          cout << ans.m[i][j] % mod << " ";        	
        }
        cout << endl;
    }  
    return 0;
}

Example 2:
As we all know, the Fibonacci sequence is a sequence that satisfies the following properties:

• f(1) = 1

• f(2) = 1

• f(n) = f(n-1) + f(n-2) (n ≥ 2 and n is an integer)

Question Description
Please find the value of f(n) mod 1000000007.

Input and output format
Input format:
Line 1: an integer n

Output format:
Line 1: Value of f(n) mod 1000000007

Input and output example
Input example #1:
5
Output example #1:
5
Input example #2:
10
Output example #2:
55
Problem solving idea 1:
According to the recursive thinking of the simple F Fibonacci sequence Yes,
but when the data is large enough, the recursive idea cannot be applied. If there is a problem that asks you to find the value of the nth item of the Fibonacci sequence, the easiest way is to directly recurse. But if the range of nn reaches 10 18 ^{18}Level 1 to 8 , recursion will not work, stable TLE. Consider matrix accelerated recursion.
The code below passes several test points: but doesn't get full marks

#include <bits/stdc++.h>
#define MAXN 1000001
#define MOD 1000000007
int n,i,F[MAXN];
int main(){
	scanf("%d",&n);
	F[1] = 1;
	F[2] = 1;
	for(i = 3; i <= n; i++){
		F[i] = (F[i-1] + F[i-2]) % MOD;	
	}
	printf("%d\n",F[n]);
	return 0;
}

Problem- solving idea 2:
Matrix accelerated recursion fast power

#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007 //Mod数
struct Matrix{//这个是矩阵的结构体
    long long ma[2][2];
};
Matrix mul(Matrix A,Matrix B){//矩阵乘法
    Matrix C;//答案矩阵
    C.ma[0][0]=C.ma[0][1]=C.ma[1][0]=C.ma[1][1]=0;//初始化
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            for(int k=0;k<2;k++){
                C.ma[i][j] = (C.ma[i][j] + A.ma[i][k] * B.ma[k][j]) % mod;
            }
        }
    }
    return C;
}
Matrix pow_mod(Matrix A,long long n){//卡苏米+矩阵乘法优化
    Matrix B;
    B.ma[0][0] = B.ma[1][1] = 1;
    B.ma[0][1] = B.ma[1][0] = 0;
    while(n) {
        if(n&1) B = mul(B,A);
        A = mul(A,A);
        n >>= 1;
    }
    return B;
}
int main(){
    long long n;
    cin >> n;
    Matrix A;
    A.ma[0][0] = 1;A.ma[0][1] = 1;
    A.ma[1][0] = 1;A.ma[1][1] = 0;//初始的数组
    Matrix ans = pow_mod(A,n);
    printf("%lld\n",ans.ma[0][1]);//输出答案
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325686006&siteId=291194637