hdoj 1576 A/B [扩展欧几里得.逆元]

本文介绍了一种解决A/B取模问题的算法,利用扩欧算法和数学思维两种方法求解(A/B)%9973,其中A很大,只给出了A%9973的值n,且A能被B整除,B与9973互质。

A/B

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4431    Accepted Submission(s): 3428


Problem Description
要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。
 

Input
数据的第一行是一个T,表示有T组数据。
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。
 

Output
对应每组数据输出(A/B)%9973。
 

Sample Input
2 1000 53 87 123456789
 

Sample Output
7922 6060
 

一,扩欧:

A/B=x  ---->A=Bx;

n=A%9973   ----->A=9973*y+n;

得:

Bx+9973y=n

BX1+9973Y1=Gcd(B,9973)=1;

所以:x=X1*n

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
void swap(int x,int y)
{
	int t;
	t=x;x=y;y=t;
}
void Exgcd(LL a,LL b,LL &x,LL &y)//&x,&y 为x,y的地址 
{
	if(b==0)
	{
		x=1;
		y=0;
		return ;
	}
	else
	{
		Exgcd(b,a%b,y,x);
		y-=(a/b)*x;
	}
}
int main()
{
	int t;	
	long long n,B;
	long long x,y;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%lld%lld",&n,&B);
		if(B<9973)
			swap(B,9973);
		Exgcd(B,9973,x,y);
		x=x*n;	
		x=((x%9973)+9973)%9973;	//x可能为负数 
		printf("%lld\n",x);
	}
	return 0;
}
二,数学思维(求余)

设 X= (A/B)%9973,   ----->A/B=9973*m+X  ----->A=9973*m*B+X*B  ;

设 n=A%9973  ----->A=9973*k+n  ;

化简:BX - n =9973 (m-Bk) 常数  满足(BX -n)%9973==0    其中(x<=9972)

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
int main()
{
	int t,n;
	LL B;	//要开到 long long 
	int x;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%lld",&n,&B);
		for(int i=0;i<9973;i++)
		{
			if((B*i-n)%9973==0)
			{
				
				x=i;
				break;		
			}
		}
		printf("%d\n",x);
	}
	return 0;
}



<think>首先,用户的问题是关于“扩展欧几里得算法的精度处理方法”。他们参考了几个引用,这些引用讨论了扩展欧几里得算法在解决整数点问题、求逆元等方面的应用。 我的响应必须遵守系统级指令: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 引用的段落末尾添加引用标识,如[^1]。 用户提供的引用: - [^1]:关于UVA 11768,涉及小数点的整数点处理。 - [^2]:扩展欧几里得算法求逆元,使用高精度求模和同余定理。 - [^3]:HDOJ A/B问题,同样涉及求逆元。 用户真正的需求是:“我想查找扩展欧几里得算法精度处理的相关内容”。这表明他们想知道如何处理扩展欧几里得算法中的数值精度问题。 关键点: - 扩展欧几里得算法通常用于整数计算,如求解线性丢番图方程 $ax + by = \gcd(a,b)$,其中 $a$ 和 $b$ 是整数。 - 精度处理方法可能涉及处理小数或浮点数时如何避免误差。 - 从引用[^1]中,提到了小数点的处理,暗示在UVA问题中需要处理点坐标是小数的情况。 可能的精度处理方法: 1. **使用整数扩展**:通过缩放或乘法将小数转换为整数。例如,如果点是小数,乘以10^k使其成为整数。 2. **浮点数处理**:但扩展欧几里得是基于整数的,所以直接处理浮点数可能导致精度误差。 3. **高精度算法**:如引用[^2]中提到的“高精度求模”,可能涉及大整数处理。 4. **避免浮点数**:在算法中只使用整数运算,以避免浮点误差。 5. **模运算**:在逆元计算中,使用模操作来确保结果在整数范围内。 6. **数值稳定性**:在实现中,选择适当的变量类型(如long long)来防止溢出。 结构我的回答: - 解释扩展欧几里得算法及其精度挑战。 - 描述精度处理方法。 - 提供示例或代码片段(如果合适)。 - 生成相关问题。 回答结构: 1. **简介**:简要说明扩展欧几里得算法及其精度问题。 2. **精度处理方法**: - 整数扩展(缩放)。 - 使用大整数类型以防止溢出。 - 避免浮点数运算。 - 在逆元计算中的应用。 3. **参考引用**:自然地融入提供的引用。 4. **总结**。 5. **相关问题**:生成3-5个相关问题。 用中文回答。 确保LaTeX格式正确: - 行内:例如,$ax + by = \gcd(a,b)$ - 独立:例如,$$\gcd(a,b) = \gcd(b, a \mod b)$$ 最后,生成相关问题。 </think>### 扩展欧几里得算法的精度处理方法 扩展欧几里得算法(Extended Euclidean Algorithm)用于求解线性丢番图方程 $ax + by = \gcd(a,b)$,其中 $a$ 和 $b$ 是整数。该算法在解决逆元计算、整数点定位等问题中广泛应用。然而,当输入涉及小数(如坐标点)或大整数时,数值精度问题可能引发错误(例如浮点误差或溢出)。基于您提供的引用(如 UVA 11768 中的小数处理问题[^1]和求逆元时的模运算[^2][^3]),我将系统性地解释精度处理的核心方法。 #### 1. **整数扩展(缩放法)** - **原理**:当输入为小数(如坐标点含小数部分)时,避免直接使用浮点数。通过乘以一个适当因子 $k$(如 $10^d$,其中 $d$ 是小数位数),将小数转换为整数,再应用扩展欧几里得算法。最后,结果需反向缩放回原始范围。 - **公式**:设原点为 $(x_0, y_0)$ 且 $x_0, y_0$ 为小数,缩放后得整数点 $(x', y')$,其中 $x' = k \cdot x_0$,$y' = k \cdot y_0$。求解方程后,真实解 $x = x' / k$,$y = y' / k$。 - **优点**:完全避免浮点误差,确保结果为精确整数或分数。 - **示例**:在 UVA 11768 中,对小数值的坐标点乘以 $10^d$ 转换为整数点,再使用扩展欧几里得算法寻找整数解[^1]。 - **代码片段**(基于引用[^1]伪代码): ```cpp double point_x = 3.14; // 输入小数坐标 int k = 100; // 缩放因子(小数位数 d=2) int scaled_x = static_cast<int>(point_x * k); // 转换为整数 // 应用扩展欧几里得算法求解 scaled 方程 // 结果除以 k 还原 ``` #### 2. **高精度整数处理(防止溢出)** - **原理**:当 $a$ 或 $b$ 为大整数时,使用大整数类型(如 `long long` 或高精度库)存储变量,并在算法中避免中间变量溢出。 - **关键步骤**: - 递归计算 $\gcd(a,b)$ 时,确保每次迭代的余数 $r$ 和系数 $x, y$ 使用足够宽的数据类型。 - 结合模运算(同余定理)简化计算,如在求逆元时,使用 $x \equiv a^{-1} \mod n$ 避免大数除法。 - **公式**:对于逆元计算,扩展欧几里得算法求解 $ax \equiv 1 \mod n$,结果通过 $x = (x \mod n + n) \mod n$ 归一化到 $[0, n-1]$ 范围[^2][^3]。 $$\text{逆元 } b^{-1} \mod n = x \quad \text{其中 } ax + ny = 1$$ - **示例**:引用[^2]中,使用 `long long` 存储变量,并通过模运算确保结果在可接受范围内:`bni = (x + 9973) % 9973;`。 - **优点**:防止整数溢出,保持算法精度。 #### 3. **避免浮点数运算(算法设计优化)** - **原理**:扩展欧几里得算法本质为整数运算,应杜绝浮点数参与核心计算(如除法或比较)。需在预处理阶段将所有输入转换为整数。 - **方法**: - 输入验证:检查小数部分是否可通过缩放精确转换(e.g., $0.25$ 可转为 $1/4$)。 - 递归优化:在扩展欧几里得递归中,使用整数除法(`a / b`)而非浮点除法。 - 边界处理:对无整数解的情况提前终止算法(如 $\gcd(a,b) \nmid c$ 时)。 - **示例**:在引用[^3]的求逆元代码中,完全使用整数运算 `extgcd(a,n,x,y)`,并通过 `(x%n + n) % n` 归一化[^3]。 - **优点**:消除浮点误差源,提升鲁棒性。 #### 总结 扩展欧几里得算法的精度处理核心在于:**整数化输入**(缩放)、**使用大整数类型**(防止溢出)和**避免浮点数**(确保整数运算)。这些方法在 UVA 11768 和逆元计算问题中已得到验证[^1][^2][^3]。实际应用中,还需测试边界情况(如 $a=0$ 或 $b=0$),并选择编程语言的高精度库(如 Python 的 `int` 或 C++ 的 `boost::multiprecision`)。通过以上策略,可高效处理小数、大整数等场景,保证结果精确可靠。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值