扩展欧几里得算法:
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
y=0;
x=1;
return a;
}
ll ans=exgcd(b,a%b,y,x);
y-=a/b*x;
return ans;
}
扩展欧几里得算法:
void exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0){x=1;y=0;return;}
exgcd(b,a%b,x,y);
ll t=x;x=y;y=t-a/b*y;
}
求b+xa==d+yc,b+xa最小的解:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int ans=exgcd(b,a%b,x,y);
int temp=x;
x=y;
y=temp-(a/b)*y;
return ans;
}
int main()
{
ll a,b,c,d,x,y;
cin>>a>>b>>c>>d;
if(b>d)//保证d>b
{
swap(a,c);
swap(b,d);
}
ll g=exgcd(a,c,x,y);
if((d-b)%g!=0)//d-b整除gcd才有解
cout<<-1<<endl;
else
{
x=x*(d-b)/g;
y=y*(d-b)/g;
y%=(a/g);
if(y>0)//求是最大负数y解
y-=a/g;
x=((d-b)-c*y)/a;
if(x<0)//到x>0,y<0才是有解的
cout<<-1<<endl;
else
cout<<a*x+b<<endl;
}
return 0;
}
poj-2142:
题意:
两种类型的砝码,每种的砝码质量a和b,要求能称出质量为d的物品,优先:|x|或|y|最小 > |x|+|y|最小
求出最小正整数 x,再根据 x求y。
求出最小正整数 y,再根据 y求x.
ac:
#include<cstdio>
#define ll long long
using namespace std;
int gcd(int a, int b)
{
return b==0?a:gcd(b,a%b);
}
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;
}
int main()
{
int a,b,n;
while(scanf("%d%d%d",&a,&b,&n)!=EOF)
{
if(a==0&&b==0&&n==0)
break;
int mod=gcd(a,b);
a/=mod;
b/=mod;
n/=mod;
int x,y,nx,ny,mx,my;
exgcd(a,b,x,y);
nx=x*n;
nx=(nx%b+b)%b;
ny=(n-a*nx)/b;
if(ny<0)ny=-ny;
my=y*n;
my=(my%a+a)%a;
mx=(n-b*my)/a;
if(mx<0)mx=-mx;
if(nx+ny>mx+my)
{
nx=mx;
ny=my;
}
printf("%d %d\n",nx,ny);
}
return 0;
}