大牛牛们说,这是矩阵快速幂,入门的题,
也是很模板的一道题吧
我先慢慢理理,
1.先是快速幂取模(百度文库有一篇超详细的推导
求得是a^b mod c(是关于数的)
int pow(int a, int b, int c)//也可能需要 long long
{
int ans = 1;
a = a % c;
while(b>0)
{
if(b&1)//判断b是否为奇数,或if(b % 2 = = 1)
ans = (ans * a) % c;
b = b/2;
a = (a * a) % c;
}
return ans;
}
定义一个矩阵的结构体,
struct Matrix
{
int m[Max][Max];
}
Matrix a,b;
3.矩阵乘法(O(n^3)
Matrix operator*(Matrix a,Matrix b)
{
int i,j,k;
Matrix c;
for (i=0;i<len;i++)
{
for (j=0;j<len;j++)
{
c.m[i][j] = 0;
for(k=0;k<len;k++)
c.m[i][j]+=(a.m[i][k]*b.m[k][j])%MOD;
}
}
return c;
}
4.矩阵相加,更简单些
Matrix operator+(Matrix a,Matrix b)
{
Matrix c;
int i,j;
for (i=0;i<len;i++)
{
for(j=0;j<len;j++)
c.m[i][j] = (a.m[i][j]+b.m[i][j])%MOD;
}
return c;
}
5.
用operator 是为了重载运算符,
Matrix operator^(Matrix a,int x)
{
Matrix p = e,q = a;
while (x)
{
if(x&1)//判断是否为奇数的另一种写法
p = p*q;//此时*被重载成矩阵的乘法了
x>>=1;//即x/=2;
q = q*q;//都不用再写取模了,已经写进*里了
}
return p;
}
6.如果不用重载,而是都写成函数,最后快速幂可以写作调用函数
Matrix Pow(Matrix a,Matrix b,int x){
while(x){
if(x&1){
b = Mul(a,b); //只将operator*改为函数名Mul,再调用就好,没什么差别
}
a = Mul(a,a);
x>>=1;
}
return b;
}
7.在知道了以上内容后,来看这一题
求f(k)%m,k的数据很大,递推会超时
想到构造矩阵会快点,总之构造矩阵很重要,大神们的图

可以看出求f(n)只需求出这个矩阵的n-9次方,再与fi相乘,就是答案
代码如下
#include <iostream>
#include <cstdio>
#include <cstring>
int k,mod;
struct matrix
{
int m[15][15];
};
matrix x,y;//定义两个要用的矩阵
void Init() //清空初始化
{
memset(x.m,0,sizeof(x.m));
for(int i=1; i<10; i++)
{
x.m[i][i-1] = 1;
}
memset(y.m,0,sizeof(y.m));
for(int i=0; i<10; i++)
{
y.m[i][i] = 1;
}
}
matrix operator*(matrix a,matrix b)
{
//也可以改成一个函数,如matrix mul(matrix a,matrix b)后面a*b改为mul(a,b)即可
matrix c;
for(int i=0; i<10; i++)
{
for(int j=0; j<10; j++)
{
c.m[i][j] = 0;
for(int K=0; K<10; K++)
{
c.m[i][j]+=(a.m[i][K]*b.m[K][j])%mod;
}
c.m[i][j]%=mod;
}
}
return c;
}
matrix Pow(matrix a,matrix b,int c)
{
//矩阵快速幂
while(c)
{
if(c&1)
{
b = a*b;
}
a = a*a;
c>>=1;
}
return b;
}
int main()
{
while(scanf("%d%d",&k,&mod)!=EOF)
{
Init();//初始化为单位矩阵
for(int i=0; i<10; i++)
scanf("%d",&x.m[0][i]);//直接存入矩阵的第一行,下面的则是InitI()初始化的单位矩阵
if(k<10)
{
printf("%d\n",k%mod);
}
else
{
matrix res=Pow(x,y,k-9);//res存的是这个矩阵的k-9次方,下面还需与f1到f9相乘
int ans = 0;
for(int i=0; i<10; i++)
{
ans+=(res.m[0][i]*(9-i))%mod;
ans%=mod;
}
printf("%d\n",ans);
}
} return 0;
}
多做几道题,一定要亲手a掉