(矩阵)快速幂

(以HDU 1757 为例)
今天完成了(矩阵)快速幂的初步学习,主要有几点问题需要注意。
1.快速幂主要知道其+,*,-,^,()……都能拆开求余就好(除法不能)

2.此类题大都数据大,定义应为long long型,并且可能是scanf

3.矩阵快速幂
核心是构造数组
HDU1757算法思路如下图(盗)
算法思路

4.对于不同的题,需要一些小的修改,主要是经过数学推导,是矩阵相乘后能够得到f(x),然后排列a0……a9(例),f(0)……f(9)位置。

5.运算时通过 ( 构造数组^n ) 就类似于快速幂了

6.代码中的注解

Mm3.a[i][j]+=(Mm1.a[i][h]*Mm2.a[h][j]);///注意这两行
Mm3.a[i][j]%=m;///(接上行)

这两行,最开始写成了

Mm3.a[i][j]+=(Mm1.a[i][h]*Mm2.a[h][j])%m;

debug了几天,这里情况是 Mm3=Mm3+(·····)%m;最后可能Mm3>=m(出错),所以应该对结果求余;

一些无关类题的小贴士
1.掌握矩阵的运算
2.以结构体创建数组,使得函数可以方便的ruturn (node)

附上HDU1757代码

#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#include<set>
#include<iterator>
#include<algorithm>
#include<stdio.h>

using namespace std;

const int N=10;
int k,m;
int cc;

struct node{
    int a[N+1][N+1];
};

node M0,M1;

node Mchen1(node Mm1,node Mm2){///10*10矩阵相乘
    node Mm3;
    for(int i=0;i<=9;i++){
        for(int j=0;j<=9;j++){
            Mm3.a[i][j]=0;
            for(int h=0;h<=9;h++){
                Mm3.a[i][j]+=(Mm1.a[i][h]*Mm2.a[h][j]);///注意这两行
                Mm3.a[i][j]%=m;///(接上行)
            }
        }
    }
    return Mm3;
}

node quickpow(node m,int N)///利用位运算来简化操作,完成矩阵相乘m^N
{
    node ans;
    for(int i=0;i<=9;i++)
     for(int j=0;j<=9;j++)
      ans.a[i][j]=(i==j);
    while(N)
    {
        if(N&1)
            ans=Mchen1(ans,m);
        m=Mchen1(m,m);
        N>>=1;
    }
    return ans;
}

int main()
{
    while(cin>>k>>m){
        memset(M1.a,0,sizeof(M1.a));
        memset(M0.a,0,sizeof(M0.a));///M0————10*1   M1——10*10
        for(int i=0;i<=9;i++){cin>>M1.a[0][i];}
        for(int i=0;i<=8;i++){M1.a[i+1][i]=1;}
        for(int i=0;i<=9;i++){M0.a[i][0]=9-i;}
        if(k<=9){cout<<k<<endl;continue;}
        M1=quickpow(M1,k-9);
        M1=Mchen1(M1,M0);
        cout<<M1.a[0][0]%m<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值