数学专题B2—裴蜀定理

ooliver OI

数学专题B2—裴蜀定理

P4549 裴蜀定理

裴蜀定理

ax+by=gcd(x,y)

题目思路

显然由前置知识可知: 对于当前的 ans 和 Ai, ans=gcd(ans,|Ai|) 所以代码如下:

#include
using namespace std;
#define int long long
signed main(){
	int n,x,ans;
	cin>>n>>ans;
	for(int i=2;i>x;
		ans=abs(__gcd(ans,abs(x)));
	}
	cout
`#include
using namespace std;
#define int long long
signed main(){
	int n,x,ans;
	cin>>n>>ans;
	for(int i=2;i
		cin>>x;
		ans=abs(__gcd(ans,abs(x)));
	}
	cout
	return 0;
}`

P1082 同余方程

扩展欧几里得

扩展欧几里得是用来解决 ax+by=gcd(x,y) 的一组解的。 设一组解为 x1,y1,一组解为 x2,y2 根据欧几里得算法(辗转相除法)可知:ax1+by1=bx2+(amodb)y2, 所以就有: ax1+by1amp;=bx2+(amodb)y2ax1+by1amp;=bx2+(a-b·⌊ab⌋)y2ax1+by1amp;=ay2+b(x2-⌊ab⌋y2) 解得: \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;
}
`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 的最小正整数解, 又因为其保证了有解, 所以我们可以知道 gcd(a,b)=1。 所以直接扩欧。 代码:

#include
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
`#include
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
	return 0;
}`

P1516 青蛙的约会

题目可以简化为求出一个最小的 k 使得:x+mk≡y+nk(modL) 开始吟唱: x+mkamp;≡y+nk(modL)∴x+mk-y-nkamp;=zL(z∈N*)x-y+k(m-n)amp;=zLzL+k(n-m)amp;=x-y 令 x0=n-m,y0=L,c=x-y,g=gcd(M,L), 则有 kx0+zy0=c, 此时就可以用扩欧求出 kx0+zy0=g 的一组解。 设该解为 x1,y1, 则继续吟唱: kx1+zy1amp;=gkx1cg+zy1cgamp;=c∵k(x1cg+dz)+z(y1cg-dk)amp;=c∴x0amp;=x1cg+dzx0↓amp;⟹d↓∵db,daamp;∈N*,∴dminamp;=1g.∴x0minamp;=(x1cgmodbg+bg)modbg 所以得到代码:

#include
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
`#include
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(a10) a1=-a1,c1=-c1;
	g=exgcd(a1,b1);
	if(c1%g) cout"Impossible";
	else cout
	return 0;
}`