矩阵快速幂的初识POJ 3734 Blocks

参考出处:www.cnblogs.com/yan-boy/archive/2012/11/29/2795294.html

www.cnblogs.com/cmmdc/p/6936196.html

blog.csdn.net/clz16251102113/article/details/81152161

整数快速幂的基本结构:

1 int KSM(int x,int n){
2     int res=x,ans=1;
3     while(n){
4         if(n&1)ans=ans*res;
5         res=res*res;
6         n>>=1;
7     }
8     return ans;
9 }

整数快速幂的是将一个res的n次方通过将n转化二进制的方式,从低位到高位依次通过不断成倍r增加es,当对应n的二进制位为1时,将此时的res乘积到结果ans中,将求res的n次幂的时间复杂度降为log(n),并且将求幂运算的内部过程显示出来,我们可以对其内部的过程进行操作(例如求模取余)。

而矩阵快速幂这是将res和ans的类型转为矩阵,通过编写矩阵乘法可以利用矩阵的优点解决许多赋值问题。

假设一个n*n的矩阵,它的矩阵快速幂的模板如下:

 1 struct node{
 2     int a[n][n];
 3 }res,ans;
 4 node MatrixMul(node p,node q){
 5     node temp;
 6     for(int i=0;i<n;i++)
 7         for(int j=0;j<n;j++){
 8             temp.a[i][j]=0;
 9             for(int k=0;k<n;k++)
10                 temp.a[i][j]=temp.a[i][j]+p.a[i][k]*q.a[k][j];
11         }
12     return temp;
13 }
14 node KSM(int n,int N){
15     for(int i=0;i<n;i++)
16         for(int j=0;j<n;j++)
17             ans.a[i][j]=(i==j);
18     while(N){
19         if(N&1)ans=MatrixMul(ans,res);
20         res=MatrixMul(res,res);
21         n>>=1;
22     }
23     return ans;
24 }

POJ 3734 Blocks代码:

#include<cstdio>
#define ll long long
#define MOD 10007
const int N=15;
struct node{
    int a[N][N];
}s,e;
//矩阵快速幂
//矩阵乘法 
node mul(node c,node d){
    node temp;
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            temp.a[i][j]=0;
            for(int k=0;k<3;k++){
                temp.a[i][j]=(temp.a[i][j]+c.a[i][k]*d.a[k][j])%MOD;
            }
        }
    }
    return temp;
}
//快速幂 
node f(node s,ll n){
    node temp;
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            temp.a[i][j]=(i==j);
        }
    }
    while(n){
        if((n&1)==1){
            temp=mul(temp,s);
        }
        s=mul(s,s);
        n>>=1;
    }
    return temp;
}
int main(){
    ll t,n;
    scanf("%lld",&t);
    s.a[0][0]=2;
    s.a[0][1]=1;
    s.a[0][2]=0;
    for(int i=0;i<3;i++)s.a[1][i]=2;
    s.a[2][0]=0;
    s.a[2][1]=1;
    s.a[2][2]=2;
    while(t--){
        scanf("%lld",&n);
        e=f(s,n);
        printf("%d\n",e.a[0][0]);
    }
    return 0;
}

 

posted @ 2020-04-21 13:00  边走边看哈哈  阅读(74)  评论(0)    收藏  举报