《Java语言实现快速幂取模》
快速幂取模算法的引入是从大数的小数取模的朴素算法的局限性所提出的,在朴素的方法中我们计算一个数比如5^1003%31是非常消耗我们的计算资源的,在整个计算过程中最麻烦的就是我们的5^1003这个过程
缺点1:在我们在之后计算指数的过程中,计算的数字不都拿得增大,非常的占用我们的计算资源(主要是时间,还有空间)
缺点2:我们计算的中间过程数字大的恐怖,我们现有的计算机是没有办法记录这么长的数据的,所以说我们必须要想一个更加高效的方法来解决这个问题
当我们计算AB%C的时候,最便捷的方法就是调用Math函数中的pow方法,但是有时A的B次方数字过大,即使是双精度的double也会溢出,这个时候为了得到AB%C的结果,我们会选择使用快速幂取模算法,简单快速的得到我们想要的结果。
为了防止数字溢出并且降低复杂度,我们需要用到下面的公式:
ab mod c = (a mod c)b mod c
这个公式的意思就是:积的取余等于取余的积的取余。很容易看出来这个公式是具有传递性的,这样我们可以通过不断的取余让a越来越小,防止出现溢出的情况。
理论上,有了这个公式我们就可以写代码了,通过不断的对a进行取模保证结果不会溢出,这确实能计算出较大次方的幂的模,但是这种方法的复杂度仍旧是O(N),并不快速。
为了更快速的计算出幂的模,我们还要依赖下面这个公式:
ab mod c = (a2)b/2 mod c , b为偶数
ab mod c = ((a2)b/2·a) mod c , b为奇数
这个公式很简单,原理就是不断的用a的平方来代替b,将b替换为原来的一半。因为我们通过第一个公式知道了一个数的模的相同次方的模相同(这句话说的有点绕,就是公式一的意思)。那么我们用a*a%c的结果来代替a效果是一样的。
所以根据上述的公式,我们得到复杂度O(logN)这样的计算快速幂的方法:
import java.util.Scanner; public class Main { public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int a = in.nextInt(), b = in.nextInt(), c = in.nextInt();
int res = 1;
a %= c;
for (; b != 0; b /= 2) {
if (b % 2 == 1)
res = (res * a) % c;
a = (a * a) % c;
}
System.out.println(res);
}
}
案例:
题目描述
给定a和b,输出a^b的最后一个数字。
输入格式
输入数据有多组,每组数据占一行,每行为a和b的值(0 < = a,b < = 2^30)。
输出格式
对每组输入数据,输出a^b的最后一位数字,每组数据占一行。
输入样例 复制
2 2
3 4
输出样例 复制
4
1
上述的问题就可以用 下面的代码解决 ,思路就是 a^b%10 取最后一位
import java.util.Scanner; public class Main { public static void main(String[] args) {
Scanner cin = new Scanner(System.in); while(cin.hasNext()){
int a = cin.nextInt();
int b = cin.nextInt();
if(a<0||b<0){
return;
}
System.out.println(getResult(a, b)); } } public static int getResult(int a,int b){
int res = 1;
int c = 10;
a %= c;
for (; b != 0; b /= 2) {
if (b % 2 == 1)
res = (res * a) % c;
a = (a * a) % c;
}
return res;
}
}
这个算法大概如此,第一步先a%=c是为了将a缩小一些,防止在for中第一次进行a*a的时候数字溢出。在for循环中,如果是b为奇数则令res=res*a,直接先将a乘到结果中去,最后做处理,又是为了防止数字溢出直接将res*a的结果mod c操作。这个for循环中,早晚有一天b会等于1,进入if分支,最后将res的值计算完毕mod c退出for循环,的到最后的结果。
转自:https://www.jb51.net/article/129333.htm
《Java语言实现快速幂取模》的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- 30、git 使用
Git 一. 目标 (一) Git的操作 二. Git和SVN的区别 (一) SVN优缺点 1. 优点: (1) 管理方便,逻辑明确 (2) 易于管理,集中式服务器更能保证安全性 (3) 代码一致性非 ...
- vue2.0 --- vuex (一)
之前做vue项目中没有使用vuex 一直使用vue-router 组件.路由一直的转换,烦不胜烦 今天研究一下vuex vuex是什么: vuex是专门为vue.js应用程序开发的状态管理模式. 解 ...
- 使用LibreOffice修复受损的Office文档
在工作中时常遇到Office文档损坏,用MS Office不能打开,有时候用LibreOffice(测试为4.2版本)可以打开,另存一下就好了. 此方法虽然不是100%管用,但在实际中大半都可以. 另 ...
- day14 十四、三元运算符,推导式,匿名内置函数
一.三元(目)运算符 1.就是if...else...语法糖 前提:if和else只有一条语句 # 原来的做法 cmd = input('cmd:>>>') if cmd.isdig ...
- 客户续费模型 逻辑回归 分类器 AdaBoost
客户续费模型 逻辑回归 分类器 AdaBoost
- 集合 & 深浅copy
集合: 特点:集合是可变的数据类型,但他里面的元素必须是不可变的数据类型,无序,不可重复. 创建: set1 = set({1,2,3}) 或者直接创建set2 = {1,2,3} 集合的增删查: 增 ...
- Jedis连接 HelloWorld实现
建一个Maven项目, pom里加下jedis依赖, <dependency> <groupId>redis.clients</groupId> <artif ...
- 【Java】NO.120.JDK.1.JDK8.1.001-【Java8实战】
Style:Mac Series:Java Since:2018-09-26 End:2018-09-26 Total Hours:1 Degree Of Diffculty:5 Degree Of ...
- C#设计模式(9)——装饰者模式(Decorator Pattern)(转)
一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).A ...
- 《linux就该这么学》第二节课,安装红帽7,基础命令至2.3小节的笔记
笔记 实验环境: 1.安装注意事项:使用VM12版本 安装需要稍后安装系统. 自定义硬件DVD选择镜像位置. 自定义网卡仅主机. 自定义内存:大于等于4G,给予虚拟机2G,大于2G小于 ...