温习(一)——快速幂
来源:互联网 发布:linux shutdown now 编辑:程序博客网 时间:2024/06/15 14:16
快速幂,是属于分治的一类习题,其思想如同分治,就是分而治之,所以看到题目的大数据,就要思考如何将大问题拆分成若干个相同解法的小问题,所以推导公式:
- (a^b)%k=a^(b/2)*a^(b/2)*a(b%2)
所以,这就是这道题目的一般性推导公式,这时程序就写出来了
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>long long b,p,k;long long work(int n){ if(n==0)return 1; long long tmp=work(n/2)%k; tmp=(tmp*tmp)%k; if(n&1)tmp=(tmp*b)%k; return tmp%k;}int main(){ scanf("%lld%lld%lld",&b,&p,&k); printf("%lld^%lld mod %lld=",b,p,k); b%=k; printf("%d\n",work(p)); return 0;}
当然这并不是最快的快速幂,你还可以采用更高效的方法,如二进制:
在二进制中,有一个神奇的运算叫做按位与,它的意思是如果在对其的情况下,两位都是1,取出来的结果就是1,否则就是0。在这个的基础上,我们在推导n&1的情况(n为任意整数):
若n为11,则(n)10=(11)10=(1011)2 00001011
所以,11&1———————————–00000001
00000001
这个方法可以用来判断这个数的奇偶(这不是重点),但真正神奇的是下面这一个式子:
(a^11)%k=(a^8)%k*(a^2)%k*(a^1)%k
这也是分治的思想,运用二进制,使时间复杂度缩短为log2(a)。
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>long long b,p,k;int main(){ int i,j,n,m; scanf("%lld%lld%lld",&b,&p,&k); printf("%lld^%lld mod %lld=",b,p,k); b%=k; long long tmp=b,ans=1; while(p!=0){ if(p&1){ ans=(ans*tmp)%k; } tmp=(tmp*tmp)%k; p>>=1; } printf("%lld\n",ans%k); return 0;}
这里有一道快速幂的题目:转圈游戏,这道题目是一道NOIP提高组的题目,总体来说就是要推导公式,这一题给大家思考,提供标程:
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>int work(int b,int n,int k){ if(n==0)return 1; int tmp=work(b,n/2,k)%k; tmp=(tmp*tmp)%k; if(n&1)tmp=(tmp*b)%k; return tmp%k;}int main(){ int i,j,k,n,m,x; scanf("%d%d%d%d",&n,&m,&k,&x); int b=10;b%=n; int tmp=work(b,k,n); tmp=(tmp*m)%n; tmp+=x;tmp%=n; printf("%d\n",tmp); return 0;}//公式:(x+m*10^k)%n
这里是改进版的(二进制实现):
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>int bb,pp;int main(){ int i,j,n,m,k,x; scanf("%d%d%d%d",&n,&m,&k,&x); bb=10;bb%=n;pp=k; int ans=1; while(pp!=0){ if(pp&1){ ans=(ans*bb)%n; } bb=(bb*bb)%n; pp>>=1; } ans=(ans*m)%n; ans+=x;ans%=n; printf("%d\n",ans); return 0;}//(x+m*10^k)%n
阅读全文
1 0
- 温习(一)——快速幂
- 温习设计模式(一)
- Java温习(基础语法一)
- 温习快速排序
- 快速排序温习
- 快速排序 温习 QuickSort
- 几张图快速温习js
- Java温习——变量
- Java温习——数据类型
- Android温习 —— 内存
- Java温习——方法
- Java温习——数组
- WinSock温习一
- ADO.NET温习(一)
- Linux温习(一)Linux的文件属性与目录配置
- JS温习:基础(一)变量,常量,数据类型
- 温习MFC画图——附带源码
- Java温习——JavaSE学习方法
- linux CentOS下yum安装MemCached
- Quartz中时间表达式的设置-----corn表达式
- Java解析xml的四种方法介绍
- SRS3.0 流叠图 RuntimeError: dictionary changed size during iteration
- java设计模式---单例
- 温习(一)——快速幂
- Agile&DevOps究竟谁是魔法棒
- 微信扫一扫开发
- 修改wifi验证错误次数
- OpenGL矩阵类(C++)
- js 图片校验
- 兼容ie8的ajax文件上传
- 输入一个链表,反转链表后,输出链表的所有元素。
- 批量转换编码