自己动手写Java大整数《4》扩展欧几里得和Mod逆

/*

*我把这个大整数的系列写成了Code中的项目,见https://code.csdn.net/XUE_HAIyang/bignumber

*/

之前已经完成了大整数的表示、绝对值的比较大小、取负值、加减法运算、乘法运算以及除法和余数运算。具体见我的主页前三篇博客(自己动手写Java系列
)。

这篇博客添加求大整数GCD、扩展欧几里得算法和求Mod逆的算法。

扩展欧几里得算法

说道扩展的欧几里得算法,首先我们看下简单的欧几里得算法。经典的欧几里得算法就是

计算两个整数的最大公因子的算法,所基于的原理就是GCD(a, b)=GCD(b, a%b). 不断地迭代

下去就行了。代码见

/*
		 * mod 运算,模数是一个正数,被模数可以是负数,返回mod数
		 */

		public DecimalBig Mod(DecimalBig modnumber)
		{
			DecimalBig tempthis =Zero;
			if (this.sign==-1)
				tempthis=this.DivideReminder(modnumber).Add(modnumber);
			else
				tempthis=this;
			return tempthis.DivideReminder(modnumber);
		}
		/**
	     * Returns a DecimalBig whose value is the greatest common divisor of
	     * {@code abs(this)} and {@code abs(val)}.  Returns 0 if
	     * {@code this == 0 && val == 0}.
	     *
	     * @param  val value with which the GCD is to be computed.
	     * @return {@code GCD(abs(this), abs(val))}
	     */

		public DecimalBig gcd(DecimalBig val)
		{
			if(val==Zero)
				return this;
			return val.gcd(this.Mod(val));

		}

扩展的欧几里得算法不仅要计算a和b的做大公因子而且还要将其用a和b线性表出,

也就是计算出x和y使得GCD(a, b)=xa+yb;

算法我就引用<introduction to modern Computer Algebra>上的算描述了。

实现见代码

		/**
	     * Returns a DecimalBig whose value is the linear representation of
	     * {@code abs(this)} modulus {@code abs(val)}.
	     *
	     * 这里边我们返回的是x使得x*this+yval=GCD(this,val);
	     * 如果return为t0则返回的是y使得x*this+yval=GCD(this,val)。
	     */
		    private DecimalBig ExtGCD(DecimalBig val)
			{
				DecimalBig r0=this, r1=val;
				DecimalBig s0=One, s1=Zero;
				DecimalBig t0=Zero, t1=One;
				DecimalBig temp_r, temp_s, temp_t;

				while(r1.Compare(Zero)!=0)
				{
					DecimalBig q=r0.Divide(r1);
	<span style="white-space:pre">				</span>temp_r=r0.Substract(q.Multiply(r1));
<span style="white-space:pre">					</span>temp_s=s0.Substract(q.Multiply(s1));
<span style="white-space:pre">					</span>temp_t=t0.Substract(q.Multiply(t1));
<span style="white-space:pre">					</span>

					r0=r1;r1=temp_r;
					s0=s1;r1=temp_s;
					t0=t1;r1=temp_t;

				}

				return s0;

			}
			

求Mod逆的算法。

扩展的欧几里得算法已经实现了,求mod 逆就是公因子是1的特例

	/**
	     * Returns a DecimalBig whose value is the greatest common divisor of
	     * {@code abs(this)} and {@code abs(val)}.  Returns 0 if
	     * {@code this == 0 && val == 0}.
	     *
	     * @param  val value with which the GCD is to be computed.
	     * @return {@code GCD(abs(this), abs(val))}
	     */
		public DecimalBig Inv_Mod(DecimalBig val)
		{

			if (val.sign != 1)
	            throw new ArithmeticException("DecimalBig: modulus not positive");
			if (this.gcd(val).Compare(One)==1)
				throw new ArithmeticException("DecimalBig: modulus and this have commen dividor >1 ");

			return this.ExtGCD(val);

		}

自己动手写Java大整数《4》扩展欧几里得和Mod逆

时间: 2024-08-29 01:06:22

自己动手写Java大整数《4》扩展欧几里得和Mod逆的相关文章

自己动手写Java大整数《3》除法和十进制转换

之前已经完成了大整数的表示.绝对值的比较大小.取负值.加减法运算以及乘法运算.具体见前两篇博客(自己动手写Java * ). 这里添加除法运算. 另外看到作者Pauls Gedanken在blog(http://paul-ebermann.tumblr.com/post/6312290327/big-numbers-selfmade-part-2-14-conversion-from)中的转换十进制数到大整数的方法,这里一并列出. 除法 除法使用经典的除法法则,但是有几个需要注意的问题,下面列出

【64测试20161112】【Catalan数】【数论】【扩展欧几里得】【逆】

Problem: n个人(偶数)排队,排两行,每一行的身高依次递增,且第二行的人的身高大于对应的第一行的人,问有多少种方案.mod 1e9+9 Solution: 这道题由1,2,5,14 应该想到Catalan数,但是我却花了两个小时去找递推式. 首先 Catalan数 : 基本规律:1,2,5,14,42,132,.......... 典型例题: 1.多边形分割.一个多边形分为若干个三角形有多少种分法. C(n)=∑(i=2...n-1)C(i)*C(n-i+1) 2.排队问题:转化为n个人

暑期学习日记二—利用扩展欧几里得求逆元

最近学习了扩展欧几里得和乘法逆元的关系,在这里写一下巩固一下记忆 扩展欧几里得是什么呢,在这就不详解了,可以自行百度,主要来说,对于 求解ax ≡ 1(mod n)来说,当gcd(a,n)=1时,证明逆元存在,若不等于1,则证明逆元不存在. 那么当逆元存在时,我们要如何求它的逆元呢? 首先是扩展欧几里得定理,先将式子转换成 ax-ny = 1 的形式,然后我们要通过扩展欧几里得定律去获得它的最大公约数,还有它的一组解 X0,Y0 1 int exgcd(int a, int b, int &x,

[Java]#从头学Java# Java大整数相加

重操旧业,再温Java,写了个大整数相乘先回顾回顾基本知识.算法.效率什么的都没怎么考虑,就纯粹实现功能而已. 先上代码: 1 package com.tacyeh.common; 2 3 public class MyMath { 4 5 public static String BigNumSum(String... n) { 6 int length = n.length; 7 StringBuilder result = new StringBuilder(); 8 //这里判断其实不需

HDU1576(扩展欧几里得)

A/B Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4252    Accepted Submission(s): 3277 Problem Description 要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1). Input 数据的第一行是一个T

hdu_1576A/B(扩展欧几里得求逆元)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1576 A/B Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4020    Accepted Submission(s): 3091 Problem Description 要求(A/B)%9973,但由于A很大,我们只给出n(n=A%99

【POJ 1061】青蛙的约会(扩展欧几里得)

[POJ 1061]青蛙的约会(扩展欧几里得) Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 103473   Accepted: 20116 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它

UVa 11768 格点判定(扩展欧几里得求线段整点)

https://vjudge.net/problem/UVA-11768 题意: 给定两个点A(x1,y1)和B(x2,y2),均为0.1的整数倍.统计选段AB穿过多少个整点. 思路: 做了这道题之后对于扩展欧几里得有了全面的了解. 根据两点式公式求出直线 ,那么ax+by=c 中的a.b.c都可以确定下来了. 接下来首先去计算出一组解(x0,y0),因为根据这一组解,你可以写出它的任意解,其中,K取任何整数. 需要注意的是,这个 a' 和 b' 是很重要的,比如说 b' ,它代表的是x每隔 b

poj1061--青蛙的约会--扩展欧几里得

Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的.但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的.为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面. 我们把这