欧几里得及其扩展

12 篇文章 0 订阅
  • 辗转相除法

用途:求解a,b两数的最大公约数 

定理:gcd(a,b)=gcd(b,a%b)  前提:b \neq 0

语言表述为:两个整数的最大公约数等于其中较小的那个数和两数相除余数的最大公约数

有了这个定理,可在几乎是log的时间复杂度内求得最大公约数

int gcd(int a,int b)
{
    if(!b) return a;
    return gcd(b,a%b);
}

 其定理延申:我们知道gcd(a,b)=gcd(b,a%b)=gcd(a%b, b )

而我们知道a\equiv c (mod\cdot b)a=c+\left \lfloor \frac{a}{b} \right \rfloor \cdot ba-b=c+\left \lfloor \frac{a}{b} -1\right \rfloor \cdot b

则要求gcd(b,a-b),等价于求gcd(a,c)

因此gcd(a,b)=gcd(a-b,b) ,这样一看,如果求多个数的最大公约,可化成差分的形式

 所以一个树状数组维护原差分数组,一个线段树可以区间查询,因此可以维护区间上的最大公约

  •  扩展欧几里得

 我们想要在辗转相除的过程中,找寻有用的信息,这里有个exgcd详解

扩欧的目标是求解一组a \cdot x+b \cdot y=c的整数解,然后通过扩倍求出通解

首先考虑不定方程有整数解的条件:gcd(a,b)|c

很好证明,将上式等号左右同除gcd(a,b),等号左侧为整数,要想求得整数解的x,y,一定会有\frac{c}{ gcd(a,b) }\in\mathbb{Z},故条件成立

这样,问题转变为求解a \cdot x+b \cdot y=gcd(a,b),我们假设x_1,y_1为该式的一组整数解,等式两边同乘\frac{c}{gcd(a,b)},导成a\cdot \left( x_1 \cdot \frac{c}{gcd(a,b)} \right )+b\cdot \left( y_1 \cdot \frac{c}{gcd(a,b)} \right ) =c,对应a \cdot x_2 + b\cdot y_2 = c

x_{2} = \left( x_1 \cdot \frac{c}{gcd(a,b)} \right )y_2 = \left( y_1 \cdot \frac{c}{gcd(a,b)} \right )

考虑如何求上式,首先看看裴蜀定理

 故一定存在x,y, x_1, y_1,使得a \cdot x+b \cdot y=gcd(a,b)b \cdot x_1+a%b \cdot y_1=gcd(b,a%b)

我们知道左右两式相等,a(x-y_1) + b(y-(x_1-\left \lfloor \frac{a}{b} \right \rfloor y_1))=0,若想上式对一切a,b成立,就有x=y_1y=(x_1-\left \lfloor \frac{a}{b} \right \rfloor y_1),满足递归的条件,因此可以写出代码

void exgcd(int a,int b,int &d,int &x,int &y)
{
	if(!b) d=a,x=1,y=0;
	else
	{
		exgcd(b,a%b,d,x,y);
		int tmp=x; x=y; y=tmp-(a/b)*y;
	}
	return ;
}

另一种简短写法: 

void exgcd(int a,int b,int &x,int &y)
{
    if(!b) {x=1; y=0; return ;}
    exgcd(b,a%b,y,x); y-=a/b*x;
    return ;
}
  • 求解线性同余方程

给定整数a,b,m,求一整数x满足a \cdot x \equiv b (mod \cdot m),或给出无解,由于未知数指数为1,也叫线性同余方程。a \cdot x \equiv b (mod \cdot m)等价为a \cdot x-bm的倍数,不妨设为- y倍,于是我们只需要解a \cdot x+m \cdot y = b即可。

定理:a,b,m是整数,且m> 0gcd(a,m)=d,如果d|b,则方程恰好有d个模m不同余的解,否则无解。

假设x_0为方程的任意一个解,则该方程的d个解分别为:x_{i} = x_0+i*(\frac{m}{gcd(a,m)}),其中0\leq i \leq d-1

 以上定理在求最小正整数解时极其适合

int a,b,d,x,y;
int main()
{
	a=read(); b=read();
	exgcd(a,b,d,x,y);
	printf("%d",(x%b+b)%b);
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值