Examples
input
30 60 3 1
output
17 9 4
input
10 51 5 4
output
-1
input
20 0 15 5
output
0 0 20
分析:
如果直接解 w*x + d*y = p = h*gcd(w,d) 这个方程组,最后确定通过扩展欧几里得算法 附 y 的初值y0 时要保证方程中的x, y 以及 x+y 的范围落在[0, N]内,这是一件困难的事情,所以应该先转化为求模同余方程 ax=b (mod n) 来做,需要求的只有x, y. 因为胜局数和平局数有权值。
令X1 = p/w , X2 = p%w/d, X3 = p%w%d 若原方程有解,则 (m*w+x3)%d == 0; 其中已知x3, w, d 且m的范围是 [0, x1];即解 模同余方程 m*w%d = d-x3; 其中 m的范围是 [0, x1]
//code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 1e18;
ll ddiv(ll a, ll b){
return a/b;
}
ll udiv(ll a, ll b){
return (a+b-1)/b;
}
ll exgcd(ll a, ll b, ll &x, ll &y){
if(b == 0){
x = 1;
y = 0;
return a;
}else{
ll r = exgcd(b, a%b, x, y);
ll xx = x; ll yy = y;
x = yy;
y = xx - (a/b)*yy;
return r;
}
}
ll mlr(ll a, ll n, ll b){
ll x, y, x1;
ll g = exgcd(a, n, x, y);
if(b%g != 0){
return -1;
}
x1 = (x*(b/g))%n;
return (x1+n)%n;
}
int main(){
ll n, p, w, d;
cin>>n>>p>>w>>d;
ll x1 = p/w;
ll x2 = (p%w)/d;
ll x3 = (p%w)%d;
if(p%w == 0){
if(x1 <= n){
cout<<x1<<" "<<0<<" "<<n-x1<<endl;
}else cout<<"-1\n";
return 0;
}
if(x3 == 0){
if(x1+x2 <= n) cout<<x1<<" "<<x2<<" "<<n-x1-x2<<endl;
else cout<<"-1\n";
return 0;
}
ll ans = mlr(w, d, d-x3);
if(ans == -1|| ans > x1){
cout<<-1<<endl;
}else{
x1 = x1 - ans;
x2 = (p-x1*w)/d;
if(x1+x2<=n) cout<<x1<<" "<<x2<<" "<<n-x1-x2<<endl;
else cout<<-1<<endl;
}
return 0;
}