博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
快速幂取模算法
阅读量:2353 次
发布时间:2019-05-10

本文共 2744 字,大约阅读时间需要 9 分钟。

快速幂取模算法

所谓的快速幂,实际上是快速幂取模的缩写,简单的说,就是快速的求一个幂式的模(余)。在程序设计过程中,经常要去求一些大数对于某个数的余数,为了得到更快、计算范围更大的算法,产生了快速幂取模算法。我们先从简单的例子入手:求a^b mod c

算法1.直接设计这个算法:

int ans = 1;for(int i = 1;i<=b;i++){   ans = ans * a;}ans = ans % c;

缺点:这个算法存在着明显的问题,如果a和b过大,很容易就会溢出。

我们先来看看第一个改进方案:在讲这个方案之前,要先看这样一个公式:a^b mod c = (a mod c)^c mod c 

于是不用思考的进行了改进:

算法2.改进算法:

int ans = 1;a = a % c; //加上这一句for(int i = 1;i<=b;i++){   ans = ans * a;}ans = ans % c;
  • 读者应该可以想到,既然某个因子取余之后相乘再取余保持余数不变,那么新算得的ans也可以进行取余,所以得到比较良好的改进版本。

算法3.进一步改进算法:

int ans = 1;a = a % c; //加上这一句for(int i = 1;i<=b;i++){   ans = (ans * a) % c;//这里再取了一次余}ans = ans % c;

这个算法在时间复杂度上没有改进,仍为O(b),不过已经好很多的,但是在c过大的条件下,还是很有可能超时,所以,我们推出以下的快速幂算法。

算法4.快速幂算法:

快速幂算法依赖于以下明显的公式: 

这里写图片描述

另一种证明方式:

这里写图片描述

int PowerMod(int a, int b, int c){    int ans = 1;    a = a % c;    while(b>0) {        if(b % 2 = = 1)        ans = (ans * a) % c;        b = b/2;        a = (a * a) % c;    }    return ans;}

本算法的时间复杂度为O(logb),能在几乎所有的程序设计(竞赛)过程中通过,是目前最常用的算法之一。

作者:wuyudong 

出处: 
ps:本文参考自网络

引申例题: 

2011

总时间限制: 1000ms 内存限制: 65536kB 

描述 
已知长度最大为200位的正整数n,请求出2011^n的后四位。 
输入 
第一行为一个正整数k,代表有k组数据,k<=200接下来的k行,

每行都有一个正整数n,n的位数<=200 

输出 
每一个n的结果为一个整数占一行,若不足4位,去除高位多余的0 
样例输入 
28 
792 
样例输出 
1051 
81 
5521

思路:快速幂的经典应用。就是求2011的n次方模10000的余数。

高精度方法:

#include
#include
#include
using namespace std;int b,g,t;char s[300];bool f[5005];int as[300];void fff(){ int k; for(k=t;k>=1;k--) { if(as[k]%2==1) as[k-1]+=10; as[k]/=2; } if(as[t]==0) t--; if(as[0]%2==1) {g=1;as[0]/=2;} else{g=0;as[0]/=2;}}int qmd(int a,int m) { b=1; while(t>0||as[0]>=1) { fff();if(g%2==1) b=a*b%m;a=a*a%m;}printf("%d\n",b);}int main(){ int n; int w,e,r; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",s); t=strlen(s); int p=t-1; while(p>=0) { as[t-1-p]=s[p]-'0'; p--; } t--; qmd(2011,10000); } return 0;}

比较神的方法,先打了一个模10000快速幂,发现幂是751,幂是4751,幂是4484484751,幂是4984465461751的答案都是一样的。规律就是后三位只要相同,得到的模10000的数就相同。200位的数什么类型都爆了。所以字符串读入,然后取后三位即可(别忘了本来位数就小于3位的情况啊)。然后快速幂。。

代码:

#include
#include
#include
using namespace std;char s[206];int n,k;int ans[205];int ksm(int a,int b,int c){ int ans=1; a=a%c; while(b>0) { if(b%2==1) ans=(ans*a)%c; b=b/2; a=(a*a)%c; } return ans;}int main(){ int i,j; cin>>k; for (j=1;j<=k;j++) { n=0; memset(s,'\0',sizeof(s)); cin>>s; if (strlen(s)==1) n=s[0]-'0'; else if (strlen(s)==2) n=(s[0]-'0')*10+s[1]-'0'; else if (strlen(s)==3) n=(s[0]-'0')*100+(s[1]-'0')*10+s[2]-'0'; else for(int i=strlen(s)-4;i<=strlen(s)-1;i++) n=n*10+(s[i]-'0'); cout<
<
你可能感兴趣的文章
浅析C++中的this指针及汇编实现
查看>>
关于32位程序在64位系统下运行中需要注意的重定向问题(有图有真相)(***)
查看>>
解决win10系统中截图异常放大的问题
查看>>
关于Windows高DPI的一些简单总结
查看>>
tlb文件为何而生?
查看>>
IE9 GPU硬件加速到底是实用创新还是噱头
查看>>
几种TCP连接中出现RST的情况
查看>>
IAAS、SAAS 和 PAAS 的区别、理解
查看>>
RichEdit对ole 对象的相关支持总结
查看>>
(分享)win10下双显示屏独立设置不同缩放率的方法
查看>>
管理学十大经典定理
查看>>
杨澜的一句话,却要让我记一生
查看>>
U盘使用心得
查看>>
作为程序员的心态
查看>>
struts 2 s:if标签的使用
查看>>
input 按钮背景,在IE6 IE7中不显示
查看>>
div使用margin:0px auto 不居中
查看>>
JavaScript 事件模型 事件处理机制
查看>>
Invalid character constant
查看>>
CSS浏览器兼容性问题 归纳
查看>>