【同余方程-拓展欧几里得解决】

语言可能不精练,有些地方讲得可能也不是很清楚,将就着看啦~

同余方程模板题

正解拓展欧几里得(百度上很多相关的博客)
稍微解释一下题目:
求$ a x \equiv 1 \pmod {b}$的最小整数解。

意思就是:给出\(a,b\),求最小的正整数\(x\)使得\(ax \mod b=1\)

说一下要点:

1.基本要点

大家也看到了,题目中强调了要求最小整数解,所以我们在结尾要保证两个点:
· 这个解是正整数
· 这个解最小
所以最后求出ans之后,在代码里加上这样两句:

while(x<=0)x+=b;
x%=b;

第一句保证了\(x>0\),第二句保证了\(x\)最小

2.问题的转化

说实话我也没有特别理解,但是还是稍微讲一下:
在C++下('/'=整除),\(a\mod b=a-b×(a / b)\)
然后是同余符号
\(a≡b\pmod{p}\)代表着\(a\mod p=b\mod p\),也就是我们说的同余。
所以题目中的$ a x \equiv 1 \pmod {b}$的意思也显而易见,上文也说过了..
那么接下来就是扩展欧几里得发挥作用的时候了【手动滑稽】

3.代码思路

首先!虽然题目看起来很简单,但我们是不能暴力枚举\(x\)的值的,会T得很惨!

第二,把问题转换一下,根据普通欧几里得,\(gcd(a,b)=gcd(b , a\mod b)\),又因为题中的方程的实质\(ax+by=1\),很明显,新引入的\(y\)也是一个未知数,甚至还是个负数.
对了,扩展欧几里得是用来解决形如\(ax+by=gcd(a,b)\)的方程的。
原理是,方程 \(ax + by = m\) 有解的必要条件是 \(m \mod gcd(a,b) = 0\)
下面证明过程我是写不出来,摘一段dalao的:

然后就可以疯狂套扩展欧几里得算法的模板了啊...
就是写一个exgcd函数,代码也很简单:

void exgcd(ll a,ll b)
{
	if(b==0)
	{
		x=1,y=0;
		return;
	}
	exgcd(b,a%b);
	k=x,x=y,y=k-a/b*y;
	return;
}

注意,这里的\(x\)存的是答案,所以\(x,y\)都要设置成全局变量!最后输出的时候按前面讲的处理一下就可以了...
完整代码;

#include<bits/stdc++.h>
#define FAST_IN std::ios::sync_with_stdio(false);cin.tie(NULL);
#define ll long long
using namespace std;
ll x,y,k;
inline void exgcd(ll a,ll b)
{
	if(b==0)
	{
		x=1,y=0;
		return;
	}
	exgcd(b,a%b);
	k=x,x=y,y=k-a/b*y;
	return;
}
int main()
{
	FAST_IN;
	ll a,b;
	cin>>a>>b;
	exgcd(a,b);
	while(x<=0)x+=b;
	x%=b;
	cout<<x<<endl;
	return 0;
}

ov.

posted @ 2019-07-24 19:19  摸鱼酱  阅读(399)  评论(0编辑  收藏  举报