矩阵乘法,矩阵快速幂,快速幂

矩阵乘法

在信息学竞赛中考矩阵乘法不是为了考基本运算,而是利用矩阵乘法的特性,配合快速幂求解递推式的第 n 项,以及一些图论的构造转化。

点击查看代码
Mat Mul(Mat a,Mat b){
    Mat c;
    for(int i = 0;i<n;i++){
        for(int j = 0;j<n;j++){
            c.arr[i][j] = 0;
        }
    }
    for(int i = 0;i<n;i++){
        for(int j = 0;j<n;j++){
            for(int k = 0;k<n;k++){
                c.arr[i][j] = (c.arr[i][j] + a.arr[i][k]*b.arr[k][j]);
            }
        }
    }
    return c;
}
矩阵快速幂
点击查看代码
Mat qMul(Mat a,int cnt){
    Mat ans;
    //I矩阵
    for(int i = 0;i<n;i++){
        for(int j = 0;j<n;j++){
            ans.arr[i][j] = (i==j);
        }
    }
    while(cnt>0){
        if(cnt&1){
            ans = Mul(ans,a);
        }
        a = Mul(a,a);
        cnt>>=1;
    }
    return ans;
}
快速幂
点击查看代码
int qpow(int a,int cnt,int mod){
  int res=1;
  while(cnt>0){
     if(cnt&1){
         res=res*a%mod;
     }
     a = a*a%mod;
     cnt>>=1;
   }
   return res;
}
例题一

https://ac.nowcoder.com/acm/contest/26656/1016
Fib函数的前n项的平方和等于F(n)*F(n+1);
利用矩阵快速幂求出F(n)和F(n+1)即可

点击查看代码
#include<bits/stdc++.h>
#define int long long
int mod = 1e9+7;
using namespace std;
struct Mat{
    int arr[20][20];
};
int n = 2;
Mat Mul(Mat a,Mat b){
    Mat c;
    for(int i = 0;i<n;i++){
        for(int j = 0;j<n;j++){
            c.arr[i][j] = 0;
        }
    }
    for(int i = 0;i<n;i++){
        for(int j = 0;j<n;j++){
            for(int k = 0;k<n;k++){
                c.arr[i][j] = (c.arr[i][j] + a.arr[i][k]*b.arr[k][j])%mod;
            }
        }
    }
    return c;
}
Mat qMul(Mat a,int cnt){
    Mat ans;
    //I矩阵
    for(int i = 0;i<n;i++){
        for(int j = 0;j<n;j++){
            ans.arr[i][j] = (i==j);
        }
    }
    while(cnt>0){
        if(cnt&1){
            ans = Mul(ans,a);
        }
        a = Mul(a,a);
        cnt>>=1;
    }
    return ans;
}
signed main(){
    int num;
    cin>>num;
    Mat node;
    int c[2][2] = {1,1,
                   1,0};
    for(int i = 0;i<2;i++){
        for(int j = 0;j<2;j++){
            node.arr[i][j] = c[i][j];
        }
    }
     Mat nodel;
     int d[2][2] = {1,0,
                   1,0};
    for(int i = 0;i<2;i++){
        for(int j = 0;j<2;j++){
            nodel.arr[i][j] = d[i][j];
        }
    }
    Mat ans = Mul(qMul(node,num-1),nodel);//前项为矩阵的n-1次方,最后乘以{fib2,fib1};
   int res = (ans.arr[0][0]*ans.arr[1][0])%mod;
    cout<<res;
}
例题二

https://ac.nowcoder.com/acm/problem/18264
由题意可得:f[n−1] * f[n+1]−f[n] * f[n] = f[n-1] * f[n]-f[n-1]*f[n-1]
n的数据范围过大,远超出1e18,此提示规律题
不难发现n为奇数时,答案为1,为偶数时,答案为-1

点击查看代码
#include<bits/stdc++.h>
using namespace std;
string s;
int main(){
   cin>>s;
   int num = s.length();
   if((s[num-1]-'0')%2==1) cout<<-1<<endl;
    else cout<<1<<endl;
}
posted @ 2022-12-22 14:35  重生之我是菜鸟  阅读(32)  评论(0)    收藏  举报