扩展欧几里得算法模板(希望永远不要搞懂了)
来源:互联网 发布:手机淘宝查看历史价格 编辑:程序博客网 时间:2024/06/06 18:03
扩展欧几里得
上述谈到的最大公约数算法是数学家欧几里德提出的,同时,他也提出了扩展欧几里德算法来解决整数二元一次不定方程问题。
整数二元一次不定方程
形如a*x+b*y=c(a,b均不为0)的方程,a,b,c都是整数,求(x,y)的整数解。
1 判断是否有解
整数二元一次不定方程有解的充分必要是gcd(a,b)|c。如果不能整除则无解。
2 扩展欧几里德求特解
欧几里德给出了计算a*x+b*y=gcd(a,b)的解法
long long exgcd(long long a,long long b,long long &x,long long &y)
{
if (b==0) { x=1,y=0; return a; }
long long d=exgcd(b,a%b,x,y);
long long tmp=x;
x=y;
y=tmp-a/b*y;
return d;
}
3 通解
a*x+b*y=gcd(a,b)在有解并求出特解(x,y)的情况下,通解可以表示为
对于一般式a*x+b*y=c,如果有解,只需把a*x+b*y=c的特解乘上c/gcd(a,b)即可得到其特解,通解还是一样的公式。
4 例子
求出特解和一个通解
int main(int argc, char* argv[])
{
long long a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
long long x,y,d;
d=exgcd(a,b,x,y);
if (c%d!=0) printf("No solution!\n");
else
{
a/=d,b/=d,c/=d;
x*=c,y*=c;
printf("特解: %lld %lld\n",x,y);
printf("一个通解: %lld %lld\n",x+b,y-a);
}
return 0;
}
请思考一下,如何求出不定方程的正整数解个数。
依然很简短,相比欧几里德算法,只是多加了几个语句而已。
这就是理论部分,欧几里德算法部分我们好像只能用来求解最大公约数,但是扩展欧几里德算法就不同了,我们既可以求出最大公约数,还可以顺带求解出使得: a*x + b*y = gcd 的通解 x 和 y
扩展欧几里德有什么用处呢?
求解形如 a*x +b*y = c 的通解,但是一般没有谁会无聊到让你写出一串通解出来,都是让你在通解中选出一些特殊的解,比如一个数对于另一个数的乘法逆元
什么叫乘法逆元?
这里,我们称 x 是 a 关于 m 的乘法逆元
这怎么求?可以等价于这样的表达式: a*x + m*y = 1
看出什么来了吗?没错,当gcd(a , m) != 1 的时候是没有解的这也是 a*x + b*y = c 有解的充要条件: c % gcd(a , b) == 0
接着乘法逆元讲,一般,我们能够找到无数组解满足条件,但是一般是让你求解出最小的那组解,怎么做?我们求解出来了一个特殊的解 x0 那么,我们用 x0 % m其实就得到了最小的解了。为什么?
可以这样思考:
x 的通解不是 x0 + m*t 吗?
那么,也就是说, a 关于 m 的逆元是一个关于 m 同余的,那么根据最小整数原理,一定存在一个最小的正整数,它是 a 关于m 的逆元,而最小的肯定是在(0 , m)之间的,而且只有一个,这就好解释了。
可能有人注意到了,这里,我写通解的时候并不是 x0 + (m/gcd)*t ,但是想想一下就明白了,gcd = 1,所以写了跟没写是一样的,但是,由于问题的特殊性,有时候我们得到的特解 x0 是一个负数,还有的时候我们的 m 也是一个负数这怎么办?
当 m 是负数的时候,我们取 m 的绝对值就行了,当 x0 是负数的时候,他模上 m 的结果仍然是负数(在计算机计算的结果上是这样的,虽然定义的时候不是这样的),这时候,我们仍然让 x0 对abs(m) 取模,然后结果再加上abs(m) 就行了,于是,我们不难写出下面的代码求解一个数 a 对于另一个数 m 的乘法逆元:
- 扩展欧几里得算法模板(希望永远不要搞懂了)
- 扩展欧几里得算法(模板)
- 欧几里得, 扩展欧几里得算法模板
- 数学(扩展欧几里得算法)经典模板
- 欧几里得算法与扩展欧几里得算法模板
- [模板] 扩展欧几里得算法详解
- 【模板】【数论】扩展欧几里得算法
- 欧几里得算法(+扩展)
- (扩展)欧几里得算法
- 扩展欧几里得算法模板题 zoj 3609
- 【扩展欧几里得算法】HDU1576A/B【模板】
- 扩展欧几里得算法——模板整理
- 欧几里得算法(gcd)和扩展欧几里得
- Romantic(扩展欧几里得算法)
- 扩展欧几里得算法(2)
- HDU1576(扩展欧几里得算法)
- 扩展欧几里得算法(exgcd)
- 欧几里得+扩展欧几里得(转载、模板)
- python eval()函数的妙用和滥用
- 完全自动化测试
- TCP服务端收到syn但是不回复syn ack问题分析
- 【数论定理】卢卡斯定理
- 数据结构之队列的链式表示及其实现
- 扩展欧几里得算法模板(希望永远不要搞懂了)
- Unity IOS项目切换场景时概率性闪退的分析与解决方案
- 提高面试代码质量的三要素
- Recycleview添加分割线
- 求jstree大神指导
- Fully Convolutional Networks for Semantic Segmentation
- Spring MVC 学习总结(二)——控制器定义与@RequestMapping详解
- 原生Js的几种时间效果
- Android TV 笔记