题目来源:http://codeforces.com/contest/1244/problem/C
直接扩展欧几里得求一组最小和整数解,但要确保x+y<=n,并且x*w+y*d==p,注意一下p的数据范围1e17,有爆精度的危险所以给他做一下处理。
·不清楚的可以看下图的一些计算,具体的实现代码中有注释。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
if(b==0)
{
return a;
}
return gcd(b,a % b);
}
void ex_gcd(ll a,ll b,ll &x,ll &y)
{
if(b==1)
{
x=1;
y=1-a;
}
else
{
ll x1,y1;
ex_gcd(b,a% b,x1,y1);
x=y1;
y=x1-x*(a/b);
}
}
int main()
{
ll m,n,k,hh;
cin>>hh>>k>>m>>n;
{
if(k==0)//0的情况很明显
{
printf("0 0 %I64d",hh);
return 0;
}
ll g=gcd(m,n);
ll x,y;
ll x2,x1;
if(k%g!=0)//一定是整数解
{
printf("-1");
return 0;
}
m/=g;
n/=g;
ex_gcd(m,n,x,y);//先解出gcd为1的m*x+n*y==1
x1=(((k/g)%n)*(x%n))%n;//怕k爆精度,所以先取余,因为k%g==0才有解所以g整除k
x1=(x1%n+n)%n;//保证是最小整数解
x2=(k/g-m*x1)/n;
if(x2<0)
x2=-x2;
y=((k/g%m)*(y%m));//同理
y=(y%m+m)%m;
x=(k/g-n*y)/m;
if(x<0)
x=-x;
if(x+y>x1+x2)//比较两组解哪个更小,也就是更优
{
x=x1;
y=x2;
}
if(x+y<=hh&&m*x+n*y==k/g)//注意判断
{
printf("%I64d %I64d %I64d",x,y,hh-x-y);
}
else
printf("-1");
}
return 0;
}