数学专题B2—裴蜀定理

用户头像 发布于 29 天前 243 次阅读 OI


数学专题B2—裴蜀定理

P4549 裴蜀定理

裴蜀定理

$ax+by=\text{gcd}(x,y)$

题目思路

显然由前置知识可知:
对于当前的 $ans$ 和 $A_i$,
$ans=\text{gcd}(ans,|A_i|)$
所以代码如下:

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main(){
	int n,x,ans;
	cin>>n>>ans;
	for(int i=2;i<=n;i++){
		cin>>x;
		ans=abs(__gcd(ans,abs(x)));
	}
	cout<<ans;
	return 0;
}

P1082 同余方程

扩展欧几里得

扩展欧几里得是用来解决 $ax+by=\text{gcd}(x,y)$ 的一组解的。
设一组解为 $x_1,y_1$,一组解为 $x_2,y_2$
根据欧几里得算法(辗转相除法)可知:$ax_1+by_1=bx_2+(a\ \text{mod} \ b)y_2$,
所以就有:
$$
\begin{align}
ax_1+by_1&=bx_2+(a \ \text{mod} \ b)y_2 \\
ax_1+by_1&=bx_2+(a- b·\lfloor\frac{a}{b} \rfloor)y_2 \\
ax_1+by_1&=ay_2+b(x_2-\lfloor\frac{a}{b} \rfloor y_2) \\
\end{align}
$$
解得:
$$
\begin{cases}
x_1=y_2 \\
y_1=x_2-\lfloor\frac{a}{b} \rfloor y_2
\end{cases}
$$
根据这个递归即可。
代码:

void exgcd(int a,int b){
	if(b==0){
		/*
		通过欧几里得算法(辗转相除法),
		最终b一定会变为0,
		这个时候gcd(a,b)=a,
		所以直接令x=1即可,y可以取任意值 
		*/
		x=1,y=0;
		return;
	}
	exgcd(b,a%b);//传递当前方程 
	int lx=x;
	x=y,y=lx-a/b*y;
}

题目思路

题目可以转化为求 $ax+by=1$ 的最小正整数解,
又因为其保证了有解,
所以我们可以知道 $\text{gcd}(a,b)=1$。
所以直接扩欧。
代码:

#include<bits/stdc++.h>
using namespace std;
int A,B,x,y;
void exgcd(int a,int b){
	if(b==0){
		x=1,y=0;
		return;
	}
	exgcd(b,a%b);
	int lx=x;
	x=y,y=lx-a/b*y;
}
int main(){
	cin>>A>>B;
	exgcd(A,B);
	x=(x%B+B)%B;//最小正整数解 
	cout<<x;
	return 0;
}

P1516 青蛙的约会

题目可以简化为求出一个最小的 $k$ 使得:$x+mk\equiv y+nk\ (\text{mod} \ L)$
开始吟唱
$$
\begin{align}
x+mk&\equiv y+nk\ (\text{mod} \ L) \\
\therefore x+mk-y-nk&=zL \ (z\in N^*) \\
x-y+k(m-n)&=zL \\
zL+k(n-m)&=x-y \\
\end{align}
$$
令 $x_0=n-m, y_0=L, c=x-y, g=\text{gcd}(M,L)$,
则有 $kx_0+zy_0=c$,
此时就可以用扩欧求出 $kx_0+zy_0=g$ 的一组解。
设该解为 $x_1,y_1$,
则继续吟唱
$$
\begin{align}
kx_1+zy_1&=g \\
k\frac{x_1c}{g}+z\frac{y_1c}{g}&=c \\
\because k(\frac{x_1c}{g}+dz)+z(\frac{y_1c}{g}-dk)&=c\\
\therefore x_0&=\frac{x_1c}{g}+dz \\
x0 \downarrow &\implies d \downarrow\\
\because db,da&\in N^*, \\
\therefore d_{\text{min}}&=\frac{1}{g}. \\
\therefore x_{0{\text{min}}}&=(\frac{x_1c}{g} \ \text{mod} \ \frac{b}{g} + \frac{b}{g}) \ \text{mod} \ \frac{b}{g} \\
\end{align}
$$
所以得到代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int xx,yy,x,y,m,n,l,g,a1,b1,c1;
int exgcd(int a,int b){
	if(b==0){
		xx=1,yy=0;
		return a;
	}
	int rtn=exgcd(b,a%b),lx=xx;
	xx=yy,yy=lx-a/b*yy;
	return rtn;
}
signed main(){
	cin>>x>>y>>m>>n>>l;
	a1=n-m,b1=l,c1=x-y;
	if(a1<0) a1=-a1,c1=-c1;
	g=exgcd(a1,b1);
	if(c1%g) cout<<"Impossible";
	else cout<<((c1*xx/g)%(b1/g)+b1/g)%(b1/g);
	return 0;
}