马上要去补快速幂的题了,在这里先巩固一下快速幂的知识点,这里重点介绍的是矩阵快速幂。
一、整数快速幂
这里不做基本知识点的讲解,因为这类的博客已经够多了,如果不会请点这里
下面直接给出模板,因为快速幂的运算数会很大,所以一般采用long long 类型,并对其进行取模运算,下面给出模板
ll mod_pow(ll x,ll n,ll mod)
{
ll ret=1;
while(n)
{
if(n&1) ret=ret*n%mod;
x=x*x%mod;
n>>=1;
}
return ret;
}
对于这个代码简单说一点,可以看到模板中有两个取模运算,取模运算的效率是十分慢的,如果可以保证中间过程不爆栈,可以考虑省去部分取模运算(这是我在某篇博客所见,感觉十分新奇,拿来分享一下);
二、矩阵快速幂
矩阵快速幂与整数快速幂的原理相同,只是将模板中的变量换为矩阵的形式,另外还要编写一个矩阵乘法的函数
这里直接给出模板,想了解基本知识点点这里
//这个代码简单了解即可,下面会给出解释
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int n = 10000+10;
int ret[n][n];
void arr_mult(int a[][n],int b[][n])
{
int tt[n][n];
memset(tt,0,sizeof(tt));
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
for(int k=0;k<n;k++)
tt[i][j]+=a[i][k]*b[k][j];
}
}
}
void arr_pow(int a[][n],int num)//注意这里n是矩阵的行数,num是次幂
{
memset(ret,0,sizeof(ret));
for(int i=0;i<n;i++) ret[i][i]=1;
while(num)
{
if(num&1) arr_mult(ret,a);
(a,a);
num>>=1;
}
}
因为本人并不喜欢用结构体去表示某些算法,所以这里只给出这种写法,但是还是给出认为写的不错的结构体的板子,或许哪一天突然爱上了结构体,算法1 算法2
白天写的这篇博客,晚上就得进行修改,因为通过做题,发现不使用结构体的矩阵快速幂很难去写,而且使用范围比较小,所以咳咳,真香!!!
这里给出结构体矩阵快速幂的代码:
struct matrix
{
int a[maxn][maxn];
}oeign,res,ste;
matrix arr_mult(matrix A,matrix B)
{
matrix t;
memset(t.a,0,sizeof(t.a));
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
for(int k=1;k<=3;k++)
{
t.a[i][j]+=A.a[i][k]*B.a[k][j];
}
}
}
return t;
}
matrix arr_mult1(matrix A,matrix B)
{
matrix t;
memset(t.a,0,sizeof(t.a));
for(int i=1;i<=3;i++)
{
for(int j=1;j<=1;j++)
{
for(int k=1;k<=3;k++)
{
t.a[i][j]+=A.a[i][k]*B.a[k][j];
}
}
}
return t;
}
这里再给出一道,矩阵快速幂的例题,也就是迫使我使用结构体的这道题,是矩阵快速幂+矩阵构造,希望大家看完第三部分后再来做此题 题目链接
解题报告
三、矩阵构造
这里算数,矩阵快速幂的应用,有一篇大神级别的博客直接分享在这里,
矩阵构造:http://www.cnblogs.com/frog112111/archive/2013/05/19/3087648.html
这里给出几点说明:
1、博客中的A,每乘一个,n就要加一,不管是在函数内,还是单独在外,常数不变。
2、构造的是(n*n)*(n*1)的形式。
PS:当题目中给出你F(n)与F(n-1)的关系时,不如来试一试矩阵的构造。