快速幂或者矩阵快速幂在算大指数次方时是很高效的,他的基本原理是二进制,下面的A可以是一个数也可以是一个矩阵(本文特指方阵),若是数就是快速幂算法,若是矩阵就是矩阵快速幂算法,用c++只需把矩阵设成一个类就可以,然后重载一下乘法就可以,注意为矩阵时则ANS=1,应该是ANS=E,E是单位矩阵,即主对角线是1其余的部分都是0的特殊方阵了。

举个例子若你要算A^7你会怎么算一般你会用O(N)的算法A^7=A*A*A*A*A*A*A也许你觉得这并不慢但是若要你算A^10000000000000000呢,是不是会觉得O(N)的算法也太慢了吧这不得算死我啊,计算机也不想算了,因为有更高效的算法我们把A的指数写成二进制,这样就有了

A^7=A^111(2)  现在我们可以这么算 令ANS=1;MULTI=A  ,N=7

while(N)

{

if(N%2==1) //亦可以写成N&1 或N%2

ANS*=MULTI;

MULTI*=MULTI;

N/=2;//c++中可以写成 N>>=1;直接用位运算更快

}

写出上面的代码的执行过程就是

ANS=1;MULTI=A;

N=7 ;N%2=1;   ANS*=MULTI; 所以ANS=A;  MULTI*=MULTI; 所以MULTI=A^2

然后 N/=2;N=3; N%2=1; ANS*=MULTI; 所以 ANS=A*A^2=A^3 ; 又MULTI*=MULTI; 所以MULTI=A^4

然后N/=2;N=1;N%2=1;ANS*=MULTI; 所以 ANS=A*A^2*A^4=A^7;又MULTI*=MULTI; 所以MULTI=A^8

然后N/=2;N=0;算法结束  是不是很巧妙呢,实际上用的乘法次数是 6次你可能觉得,那个A^7=A*A*A*A*A*A*A,不也是用了6次乘法吗有什么区别?

那是因为这个算法是log2(n)   (表示以2为底n的对数) 的复杂度,还有一个系数,大约是2 实际上计算次数就是 2*log2(n) 而普通的连乘计算的复杂度是n 乘法计算次数是n-1

这样在n很小时差别不大,但随着n的增长差距会迅速扩大,例如 n=1024时 普通方法得计算1023次乘法,但快速幂最多(因为当上面的程序执行时N的中间结果为偶数那么  ANS*=MULTI,将不会被执行,故实际的计算次数要小于 2*log2(n))只算2*log2(n) =20次乘法,是不是很快!!!!!!!!!!

但是为什么呢?好像还有点不懂。。

实际上A^7=A^1*A^2*A^4这样每次计算乘法乘的因子都是递增的,而且还是指数递增,还有这些因子是可以递推产生的就是可以利用上次的计算每次平方就可以了,这中其实是使用的二进制的思想,因为任意一个数都可以,表示成二进制,故 A^N以定可以写成

A^(一个二进制数如101010)=A^(100000)*A^(00000)*A(1000)*A^(000)*A^(10)*A^(0)=A^(2^5)*A^(2^3)*A^(2^1)

而我们的MULTI 其实是一个数列 A^1,A^2,A^4,A^8,A^16........即A^(2^0),A^(2^1),A^(2^2),A^(2^3),A^(2^4).......................注意到他的指数都是二进制的位权(不知道是不是这个名词,就像十进制的位权是 1 10 100 1000 10000,一样如1243=1*1000+2*100+3*10+4*1;而二进制的1011 是 1*2^(3)+0*2^(2)+1*2^(1)+1*2^(0) 这样是不是应该理解位权了呢?)实际上任何一个A^N都可以写成这个数列的某些项的乘积,因为N始终都可以表示成二进制,而把N表示成二进制后如果某项为1则说明需要乘上MULTI 否则不用乘上MULTI

于是就有了上面的代码,,,,哎怎么感觉我说的还是很不清楚呢?那就没办法

下面附上代码,另外一般要用快速幂的题都要取模 因为指数太大的数是会爆掉int 和long long 的

#include<iostream>
using namespace std;
#define mod 1000000007
long long quick_pow(int n,int base)
//n是指数 base是底 即计算的是base^n 当然结果是取模了的
{long long ans=1;//默认ans大于等于1因为不能算负指数long long multi=base;while(n){if(n%2) ans*=multi;ans%=mod;//由于数太大一般要取模n/=2;multi*=multi;multi%=mod;}return ans;
}int main()
{int n,base;while(cin>>n>>base)cout<<quick_pow(n,base)<<endl;return 0;
}

可能你会问了这个算法有什么用呢?其实用的更多是使用矩阵快速幂,算递推式,注意是递推式,简单的如斐波那契数列的第一亿项的结果模上10000000后是多少你还能用递推式去,逐项递推吗?当然不能,这里就可以发挥矩阵快速幂的神威了,那斐波那契数列和矩阵快速幂能有一毛钱的关系?答案是有而且很大

斐波那契的定义是f(1)=f(2)=1; 然后f(n)=f(n-1)+f(n-2) (n>=2) 我们也可以这样定义f(1)=f(2)=1; [f(n),f(n-1)]=[f(n-1),f(n-2)][1,1,1,0],其中[1,1,1,0] 是一个2*2的矩阵 上面一行是1,1,下面一行是1,0,这样就可以化简了写成[f(n),f(n-1)]=[f(2),f(1)]*[1,1,1,0]^(n-2)

化简一下

这样就可以用矩阵快速幂,快速的推出斐波那契数列的第一亿项的值了(当然是取模的值了)是不是很神奇,类似的递推式也可以,化成这种形式,用矩阵快速幂进行计算

下面附一个矩阵快速幂的代码,当然所有矩阵都是要模的

# include<cstdio>
# include<cstring>
using namespace std;
#define NUM 50
int MAXN,n,mod;
struct Matrix//矩阵的类
{int a[NUM][NUM];void init()           //将其初始化为单位矩阵{memset(a,0,sizeof(a));for(int i=0;i<MAXN;i++)a[i][i]=1;}
} A;
Matrix mul(Matrix a,Matrix b)  //(a*b)%mod  矩阵乘法
{Matrix ans;for(int i=0;i<MAXN;i++)for(int j=0;j<MAXN;j++){ans.a[i][j]=0;for(int k=0;k<MAXN;k++)ans.a[i][j]+=a.a[i][k]*b.a[k][j];ans.a[i][j]%=mod;}return ans;
}Matrix add(Matrix a,Matrix b)  //(a+b)%mod  //矩阵加法
{int i,j,k;Matrix ans;for(i=0;i<MAXN;i++)for(j=0;j<MAXN;j++){ans.a[i][j]=a.a[i][j]+b.a[i][j];ans.a[i][j]%=mod;}return ans;
}Matrix pow(Matrix a,int n)    //(a^n)%mod  //矩阵快速幂
{Matrix ans;ans.init();while(n){if(n%2)//n&1ans=mul(ans,a);n/=2;a=mul(a,a);}return ans;
}Matrix sum(Matrix a,int n)  //(a+a^2+a^3....+a^n)%mod// 矩阵的幂和
{int m;Matrix ans,pre;if(n==1)return a;m=n/2;pre=sum(a,m);                      //[1,n/2]ans=add(pre,mul(pre,pow(a,m)));   //ans=[1,n/2]+a^(n/2)*[1,n/2]if(n&1)ans=add(ans,pow(a,n));          //ans=ans+a^nreturn ans;
}void output(Matrix a)//输出矩阵
{for(int i=0;i<MAXN;i++)for(int j=0;j<MAXN;j++)printf("%d%c",a.a[i][j],j==MAXN-1?'\n':' ');
}
int main()
{freopen("in.txt","r",stdin);Matrix ans;scanf("%d%d%d",&MAXN,&n,&mod);for(int i=0;i<MAXN;i++)for(int j=0;j<MAXN;j++){scanf("%d",&A.a[i][j]);A.a[i][j]%=mod;}ans=sum(A,n);output(ans);return 0;
}

话说这是那题的代码,我不知道了

//****************************************

再给几道题,有详细的解题思路点击打开链接

//*****************************************

再介绍一题http://acm.hit.edu.cn/hoj/problem/view?id=2255

是哈工大的在线oj上的一个题目,一个类似于斐波那契的题目,题目会给出a,b,p,q,s,e, 其中f(0)=a,f(1)=b,当n>=2时 f(n)=P*f(n-1)+q*f((n-2) 求它组成的数列从第s项起一直加到第e项的和是多少,这题就不能推f(n)的矩阵乘法的递推式了,得推出他的前n项和s(n)的递推式,当然如果会推斐波那契的矩阵形式的递推形式的想必这个就不难了

推理过程如下:

F(N)=S(N)-S(N-1);

又有F(N)=P*F(N-1)+Q*F(N-2)

所以 S(N)-S(N-1)=P*(S(N-1)-S(N-2))+Q*(S(N-2)-S(N-3))

S(N)=(P+1)*S(N-1)+(Q-P)*S(N-2)-Q*S(N-3)

推到这里你应该知道怎么把它化成矩阵乘法的形式了吧?注意到右边有三个S(x)项所以矩阵递推式左边也要有三项写出来就是

化简一下

所以第s项到第e项的和就是S(E)-S(s-1) 注意是S(s-1)

OK大功告成下面就是AC代码

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define NUM 3
int MAXN=3,n;
long long const mod=1e7;
struct Matrix
{Matrix(){memset(a,0,sizeof(a));}long long a[NUM][NUM];void init()           //将其初始化为单位矩阵{memset(a,0,sizeof(a));for(int i=0;i<MAXN;i++)a[i][i]=1;}
} A;
Matrix mul(Matrix a,Matrix b)  //(a*b)%mod
{Matrix ans;for(int i=0;i<MAXN;i++)for(int j=0;j<MAXN;j++){ans.a[i][j]=0;for(int k=0;k<MAXN;k++)ans.a[i][j]+=a.a[i][k]*b.a[k][j];ans.a[i][j]%=mod;}return ans;
}
Matrix pow(Matrix a,int n)    //(a^n)%mod
{Matrix ans;ans.init();while(n){if(n%2)//n&1ans=mul(ans,a);n/=2;a=mul(a,a);}return ans;
}
void output(Matrix a)
{for(int i=0;i<MAXN;i++){for(int j=0;j<MAXN;j++)printf("%d ",a.a[i][j]);cout<<endl;}}
int main()
{//freopen("in.txt","r",stdin);long long  a,b,p,q,s,e;int T;cin>>T;while(T--){Matrix ans;cin>>a>>b>>p>>q>>s>>e;ans.a[0][0]=p+1;ans.a[0][1]=q-p;ans.a[0][2]=-q;ans.a[1][0]=1;ans.a[2][1]=1;//output(ans);int f[3]={a,a+b,a+b+p*b+q*a};long long  ss=0,ee=0;if(s<=3&&s>0)ss=f[s-1];else if(s){Matrix temp=pow(ans,s-3);for(int i=0;i<3;i++)ss+=(temp.a[0][i]*f[2-i])%mod;}if(e<=2)ee=f[e];else{Matrix temp=pow(ans,e-2);for(int i=0;i<3;i++)ee+=(temp.a[0][i]*f[2-i])%mod;}ss=(ss+mod)%mod;//取模运算要注意一下的ee=(ee+mod)%mod;cout<<(ee-ss+mod)%mod<<endl;//这里也要注意的}return 0;
}

快速幂或者矩阵快速幂相关推荐

  1. 二分幂,快速幂,矩阵快速幂,快速乘

    前言 二分幂,快速幂,矩阵快速幂在算大指数次方时是很高效的. 求 a^n 的值是多少?n是1到10^18次方的一个整数. 求一个数的n次方,朴素的算法就是直接for循环,一遍一遍的乘,a*a*a*a* ...

  2. python【数据结构与算法】快速幂and矩阵快速幂取模(看不懂你来打我)

    文章目录 1 解释快速幂 2 代码(这里就不考虑指数为小于0的情况了) 3 下面是矩阵快速幂,区别只是底数换成了矩阵 1 解释快速幂 传统的幂运算,是对底数进行连乘,时间复杂度为o(n),例如:2^1 ...

  3. 快速幂、矩阵快速幂、快速乘法

    快速幂 快速幂是我们经常用到的一种算法,快速幂顾名思义就是快速的幂运算.我们在很多题目中都会遇到幂运算,但是在指数很大的时候,我们如果用for或者是pow就会超时,这时候就用到了快速幂. 快速幂的原理 ...

  4. 数论-快速幂、矩阵快速幂、慢速乘

    文章目录 快速幂 矩阵快速幂 慢速乘 例题 HDU-2817 HDU-3117 XUJC-1395 快速幂 首先幂运算 a n a^n an就是 n n n个 a a a相乘,我们可以直接调用库函数 ...

  5. 快速幂与矩阵快速幂学习笔记

    首先附上我学习快速幂的链接 https://blog.csdn.net/qq_19782019/article/details/85621386 并从中摘抄了一些有用的东西记录下来作为总结 1.&qu ...

  6. 快速幂、快速乘、矩阵快速幂

    文章目录 一 快速幂 模板 模板例题 二 快速乘 模板 三 矩阵快速幂 例题 模板题 应用题1 应用题2 一 快速幂 目的:当我们在求f(x) = a ^ x % mod时,f(x)的结果会呈指数型增 ...

  7. 快速幂和矩阵快速幂详解+模板

    1.快速幂 一般的,我们都知道求只需要连续乘3次2就能得到,那么等于多少呢?其实这个一很简单,不就是13个2相乘吗,连续乘13次2就行了.那么,呢? 是不是要连续乘100次.1000次,我们将这类问题 ...

  8. 数论(二)快速幂 (矩阵快速幂)等比数列求和 最大公因数和最小公倍数

    快速幂 1.快速幂用于快速计算a的b次方,时间复杂度是O(log2b) 2.用于a和b比较大小的情况,常用的快速幂是带模快速幂 3.分析一个例子: 3 15=?  15=(1111)2 3e1 * ...

  9. 蓝桥杯 算法提高 递推求值(矩阵快速幂)详解

    传送门 问题描述 已知递推公式: F(n, 1)=F(n-1, 2) + 2F(n-3, 1) + 5, F(n, 2)=F(n-1, 1) + 3F(n-3, 1) + 2F(n-3, 2) + 3 ...

最新文章

  1. 企业架构研究总结(39)——TOGAF架构能力框架之架构委员会和架构合规性
  2. 如何进行高效的时间管理?
  3. dbms_rowid包的BUG问题
  4. [转载] 中华典故故事(孙刚)——21 正月剪头死舅舅
  5. Android OTA 升级之三:生成recovery.img
  6. mysql开窗函数over_sql中的开窗函数over()
  7. 转 carrer 之感
  8. 2016 CCPC 杭州
  9. python单元测试的应用_单元测试pythongui应用程序的推荐方法是什么?
  10. android Gallery实现异步加载网络图片
  11. java关闭服务_实现优雅地关闭Docker中的java服务
  12. 谷歌地球替代软件、谷歌街景、谷歌三维城市模型查看全方案
  13. nef是什么格式?nef格式用什么软件打开?nef格式怎么转换成jpg
  14. Python之marshmallow
  15. 单臂路由之一,单网口软路由实现主路由功能,光猫或交换机剩余网口实现上网功能
  16. cr全称是什么意思,城域网中的AC、BRAS、SW、SR、CR是什么意思
  17. 调用第三方应用App
  18. 未接响铃1秒是什么意思_空调能耗等级是什么意思 家用有必要买1级空调吗 看了它就明白了...
  19. RA-L期刊投稿相关内容
  20. 智慧小区智能化视频监控系统建设方案

热门文章

  1. 老男孩linux高级架构 百度云盘下载
  2. 使用Socket类接收和发送数据
  3. 基于Seajs的可控台球碰撞游戏
  4. 减小iOS应用程序的大小
  5. IBM服务器安装与HBA卡的驱动问题
  6. 深入理解iPhone委托模式兼谈iPhone生命周期
  7. 【重点!DP】LeetCode 639. Decode Ways II
  8. FPI(Fixed-point Iteration)不动点迭代法——迭代求方程的方法
  9. 《Outlier Analysis》书籍
  10. 输出100之间的所有质数(素数)