扩展欧几里德算法

  扩展欧几里德算法求解线性方程ax+by=c
  令d=(a,b) 若此方程有解 则 c|d 否则无解
  通解x=x0+b/d*t,y=y0+a/d*t;
  令k=b/d
  则可求得x最小正数解为(x%k+k)%k

  最大负数解为(x%k-k)%k

//POJ 1061 水题
#include<cstdio>
using namespace std;
__int64 X,Y;
__int64 ex_euclid(__int64 a,__int64 b){
	if(b==0){
		X=1;
		Y=0;
		return a;
	}
	__int64 d=ex_euclid(b,a%b);
	__int64 t=X;
	X=Y;
	Y=t-(a/b)*Y;
	return d;
}
int main(){
	__int64 x,y,m,n,L;
	while(scanf("%I64d%I64d%I64d%I64d%I64d",&x,&y,&m,&n,&L)!=EOF){
		__int64 a=n-m,b=L,c=x-y;
		__int64 d=ex_euclid(a,b);
		if(c%d){
			printf("Impossible\n");
			continue;
		}
		X*=(c/d);
		Y*=(c/d);
		__int64 K=b/d;
		X=(X%K+K)%K;
		printf("%lld\n",X);
	}
	return 0;
}


//POJ 2115 纯水~
#include<cstdio>
using namespace std;
__int64 x,y;
__int64 ex_euclid(__int64 a,__int64 b){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	int d=ex_euclid(b,a%b);
	int t=x;
	x=y;
	y=t-a/b*y;
	return d;
}
int main(){
	__int64 A,B,C,k;
	while(scanf("%I64d%I64d%I64d%I64d",&A,&B,&C,&k)!=EOF){
		if(!(A||B||C||k))
		break;
		__int64 a=C,b=((__int64)1)<<k,c=B-A;
		__int64 d=ex_euclid(a,b);
		if(c%d){
			printf("FOREVER\n");
			continue;
		}
		x*=(c/d);
		y*=(c/d);
		__int64 s=b/d;
		x=(x%s+s)%s;
		printf("%I64d\n",x);
	}
	return 0;
}

/* POJ 2142 个人认为是个很好的题 有助于理解扩展欧几里德算法
有点忘记这题的细节怎么处理了 有空补上 代码先贴出来
*/
#include<cstdio>
#include<cmath>
#include<cstdlib>
using namespace std;
int X,Y;
int ex_euclid(int a,int b){
	if(b==0){
		X=1;
		Y=0;
		return a;
	}
	int d=ex_euclid(b,a%b);
	int t=X;
	X=Y;
	Y=t-a/b*Y;
	return d;
}
int main(){
	int a,b,c;
	while(scanf("%d%d%d",&a,&b,&c)!=EOF){
		if(a==0&&b==0&&c==0)
		break;
		int f=1;
		if(a<b){
			int m=a;
			a=b;
			b=m;
			f=0;
		}
		int d=ex_euclid(a,b);
		X*=(c/d);
		Y*=(c/d);
		int k=a/d;
		int y1=(Y%k+k)%k;
		int x1=(c-b*y1)/a;
		int y2=(Y%k-k)%k;
		int x2=(c-b*y2)/a;
//		printf("%d %d %d %d\n\n",x1,y1,x2,y2);
		int ans1=abs(x1)+abs(y1);
		int ans2=abs(x2)+abs(y2);
		if(ans1!=ans2){
			if(ans1<ans2){
				if(f)
				printf("%d %d\n",abs(x1),abs(y1));
				else
				printf("%d %d\n",abs(y1),abs(x1));
			}
			else{
				if(f)
				printf("%d %d\n",abs(x2),abs(y2));
				else
				printf("%d %d\n",abs(y2),abs(x2));
			}
		}
		else{
			int res1=a*abs(x1)+b*abs(y1);
			int res2=a*abs(x2)+b*abs(y2);
			if(res1<res2){
				if(f)
				printf("%d %d\n",abs(x1),abs(y1));
				else
				printf("%d %d\n",abs(y1),abs(x1));
			}
			else{
				if(f)
				printf("%d %d\n",abs(x2),abs(y2));
				else
				printf("%d %d\n",abs(y2),abs(x2));
			}
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值