(以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;
}