algorithm@ Matrix fast power
一. 什么是快速幂:
快速幂顾名思义,就是快速算某个数的多少次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高。一般一个矩阵的n次方,我们会通过连乘n-1次来得到它的n次幂。但做下简单的改进就能减少连乘的次数,方法如下:把n个矩阵进行两两分组,比如:A*A*A*A*A*A => (A*A)*(A*A)*(A*A)。这样变的好处是,你只需要计算一次A*A,然后将结果(A*A)连乘自己两次就能得到A^6,即(A*A)^3=A^6。算一下发现这次一共乘了3次,少于原来的5次。但是当n非常大的时候,其实效率也没有比直接乘号多少。
二. 二分思想求矩阵的快速幂:
首先大家要明白任何一个数都可以用二进制数来表示,比如十进制数字7可以表示为111(2),因此假设我们要求a^b,就可以把b分解成多项式,即:
b = P(n)*An+ P(n-1)*An-1+…+ P(i)*Ai+ P(i-1)*Ai-1+…+ P(0)*A0
ab= a P(n)*An + P(n-1)*An-1+…+ P(i)*Ai + P(i-1)*Ai-1 +…+ P(0)*A0= a P(n)*An * a P(n-1)*An-1 * a P(i)*Ai* …* a P(0)*A0
上面的p(i)等于0或者1,所以如果p(i)=0的话,a P(i)*Ai=a0=1. 当p(i)=1时,a P(i)*Ai=a Ai,
所以A^11就等于A^(10112)=(A^8)*(A^2)*(A^1)。这里就体现了快速的效果了:原本要进行10次乘法运算现在最多只要算4次了。(4次对应的是1011总共有4个位)。可以想象一下A的1024次幂,可以由1023次乘法运算降低到11次运算了(1024=100000000002,总共11位)。
三. 算法演示:
为了更清晰的说明快速幂算法,这里以A的11次幂为例子,配了一张图来说明,这样大家都能看得懂了哈~
将11写成1011,然后按位从右到左扫描,设置一个tmp来表示当前扫描位对应的十进制幂的大小,比如第0位对应的十进制指数是1,第3位对应的十进制指数是8,因此我们每向左前进一个扫描位,tmp就double一次,这样tmp就能表示二进制位对应的十进制幂了(tmp初始值为1)。然后我们每遇到二进制位对应数字是1时,就把结果ans和tmp相乘,并且把结果复制到ans中(ans初始值为1)。好了,现在开始运行算法:
刚开始,指针指向第0位,tmp=A,并且该位对应数字是1,所以ans=ans*tmp=A。
指针扫描到第1位,tmp也已经double一次了(tmp=A2)。该位对应数字是1,所以ans=ans*tmp=A3。
指针扫描到第2位,tmp也已经double一次(tmp=A4),该位对应数字是0,所以什么都不做,继续扫描。
指针扫描到第3位,tmp也已经double一次(tmp=A8),该位都应数字是1,所以ans=ans*tmp=A11。此时,算法结束。
四. 完整代码:
#include <iostream>
using namespace std; //计算a^bmodn
int modexp(int a,int b,int n)
{
int ret=;
int tmp=a;
while(b)
{
//基数存在
if(b&0x1) ret=ret*tmp%n;
tmp=tmp*tmp%n;
b>>=;
}
return ret;
} int main()
{
cout<<modexp(,,)<<endl;
return ;
}
algorithm@ Matrix fast power的更多相关文章
- 校赛热身 Problem B. Matrix Fast Power
找循环节,肯定在40项以内,不会证明. #include <iostream> #include <cstring> #include <string> #incl ...
- Lintcode: Fast Power 解题报告
Fast Power 原题链接:http://lintcode.com/en/problem/fast-power/# Calculate the an % b where a, b and n ar ...
- Fast Power
Calculate the a^n % b where a, b and n are all 32bit integers. Example For 2^31 % 3 = 2 For 100^1000 ...
- 论文总结(negFIN: An efficient algorithm for fast mining frequent itemsets)
一.论文整体思路: 作者提出了一种基于前缀树的数据结构,NegNodeset,其实是对之前前缀树的一种改进,主要区别在于采用了位图编码,通过这种数据结构产生的算法称为negFIN. negFIN算法高 ...
- ZJOI2017 Day1
私のZJOI Day1 2017-3-21 07:52:53 有人在暴力膜 苟-- 富贵 无相忘 ZJOI2017交流群 133135071 如果你足够厉害 如果你足够厉害 如果你足够厉害 其实完全可 ...
- POJ 3233 Matrix Power Series(二分等比求和)
Matrix Power Series [题目链接]Matrix Power Series [题目类型]二分等比求和 &题解: 这题我原来用vector写的,总是超时,不知道为什么,之后就改用 ...
- Java Algorithm Problems
Java Algorithm Problems 程序员的一天 从开始这个Github已经有将近两年时间, 很高兴这个repo可以帮到有需要的人. 我一直认为, 知识本身是无价的, 因此每逢闲暇, 我就 ...
- Lintcode: Hash Function && Summary: Modular Multiplication, Addition, Power && Summary: 长整形long
In data structure Hash, hash function is used to convert a string(or any other type) into an integer ...
- Reinforcement Learning for Self Organization and Power Control of Two-Tier Heterogeneous Networks
R. Amiri, M. A. Almasi, J. G. Andrews and H. Mehrpouyan, "Reinforcement Learning for Self Organ ...
随机推荐
- Git权威指南 读笔(2)
第七章 Git重置: Git提供了一个挽救机制,通过.git/logs目录下日志文件记录了分支的变更. master分支的日志文件.git/logs/refs/heads/master,显示最后5行: ...
- Objective-c开发中混合使用ARC
首选“Compile Sources”的位置: 选中工程->TARGETS->相应的target然后选中右侧的“Build Phases”,向下就找到“Compile Sources”了. ...
- 基于Python的TCP阻塞式echo服务器
上述问题的出现是因为没有设置listen函数 from socket import * from time import ctime HOST = '' PORT = 21567 BUFSIZ = 1 ...
- ubuntu安装svn manager
环境:系统ubuntu14.04 0. 更新软件库 sudo apt-get update sudo apt-get upgrade -y 1. 安装apache,svn,svn的apache模块 s ...
- range([start], stop[, step]):产生一个序列,默认从0开始
range([start], stop[, step]):产生一个序列,默认从0开始 >>> l = range(10) >>> l [0, 1, 2, 3, 4, ...
- PHP漏洞全解(四)-xss跨站脚本攻击
本文主要介绍针对PHP网站的xss跨站脚本攻击.跨站脚本攻击是通过在网页中加入恶意代码,当访问者浏览网页时恶意代码会被执行或者通过给管理员发信息 的方式诱使管理员浏览,从而获得管理员权限,控制整个网站 ...
- 一组神奇的 3D Gif 动图
本文由 极客范 - 黄利民 翻译自 mymodernmet.欢迎加入极客翻译小组,同我们一道翻译与分享.转载请参见文章末尾处的要求. 虽然 gif 动图/动画似乎是无处不在现在了,但有些聪明人已经把 ...
- JavaScript注入漏洞的原理及防范
初次接触: 初次接触JavaScript注入漏洞后,如果不对这种漏洞的作用机理仔细分析并提取出其发生的某种模式,你就不能做到快速的发现项目中可能存在的所有注入风险并在代码中防范. 发生模式: Java ...
- easyui源码翻译1.32--Resizable(调整大小)
前言 使用$.fn.resizable.defaults重写默认值对象 下载该插件翻译源码 源码 /** * jQuery EasyUI 1.3.2 * *翻译:qq 1364386878 Resiz ...
- H2O与Java线程同步
Java 5以前的线程同步采用syncronized和wait,notify,notifyAll来实现,比较粗糙.之后有了Lock和Condition.ReentrantLock的简单lock,unl ...