(Click here to view the original title)
Analysis of the meaning of problems
Known n, p, w, d, find values of x, y, z, and their relationship is:
x + y + z = n
x * w + y * d = p
Thinking method
When y <w, we 1e5 times by up to determine the answer enumeration
When y> = w time, resulting into a draw: y * d = (yw) * d + w * d, can be regarded as the number of draw Bureau YW, extra contribution to w * d (w * d) / w = d Bureau wins, it wins is x + d, with x y Bureau described case wins and a tie score obtained may + a x + d + y - w Bureau wins and draws obtained, while at this time + number of wins draw less, so enumerated y> where w is meaningless, can enumerate y = {0 ~ w - 1} answer
In summary, we just need to get the answer in [0, y enumeration within w) range
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<string> #include<fstream> #include<vector> #include<stack> #include <map> #include <iomanip> #define bug cout << "**********" << endl #define show(x, y) cout<<"["<<x<<","<<y<<"] " #define LOCAL = 1; using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; const int Max = 5e3 + 10; ll n, sum; ll win, draw; int main() { #ifdef LOCAL // freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); #endif scanf("%lld%lld%lld%lld", &n, &sum, &win, &draw); for(ll y = 0 ; y < win ; y ++) { if ((sum - y * draw) % win) continue; ll x = (sum - y * draw) / win; if(x + y <= n && x >= 0) { printf("%lld %lld %lld\n",x,y,n-x-y); return 0; } } printf("-1\n"); return 0; }
Extended Euclid law
Extended Euclidean Algorithm is a positive solution to this problem, from the equation: x * w + y * d = p, it is seen that exactly correspond to the extended Euclidean equation: x * a + y * b = gcd (a, b), by means of extended Euclidean formula, we can get a set of solutions x * w + y * d = p, the following steps:
1) using the extended Euclidean Evaluate Formula:
x0 * w + y0 * d = gcd(w,d)
We got x0, y0
2) The above equation both sides of the passenger k = p / gcd (w, d), must ensure that [(p% gcd (w, d)) == 0, or no solution] to obtain:
x0 * k * w + y0 * k * d = gcd(w,d) * k
which is
x0 * k * w + y0 * k * d = p
Thus, x = x0 * k, y = y0 * k is a set of solutions of the equation x * w + y * d = p, and
3) Since the x, y, z satisfy the need for
x + y + z = n
Therefore, we adjusted x, y, such that the formula is satisfied, therefore, we need to make the value of x + y is as small as possible; note w> d, as described, when the minimum value y, x + y takes a minimum value If at this time x + y <= n, described a solution, or no solution
And The x * w + y * d = p, we know that y each change: + - w / gcd (w, d), it is the minimum value of y
y = ( y0 * k ) % (w/gcd(w,d))
4) Finally, the obtained y, and z are determined the value of x, then x + y is less than the determined n, i.e. to meet the output x, y, z, or no solution described
(Note that y is required when performing a modulo operation, or will burst long long)
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<string> #include<fstream> #include<vector> #include<stack> #include <map> #include <iomanip> #define bug cout << "**********" << endl #define show(x, y) cout<<"["<<x<<","<<y<<"] " #define LOCAL = 1; using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int Max = 5e3 + 10; ll n, sum; ll win, draw; ll exgcd(ll a, ll b, ll &x, ll &y) { if (b == 0) { x = 1; y = 0; return a; } ll r = exgcd(b, a % b, x, y); ll t = x; x = y; y = t - (a / b) * y; return r; } int main() { #ifdef LOCAL // freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); #endif scanf("%lld%lld%lld%lld", &n, &sum, &win, &draw); ll x, y; ll gcd = exgcd(win, draw, x, y); if ((sum % gcd) == 0) { ll mod = win / gcd; y = ((y%mod)*(sum/gcd%mod)%mod + mod)%mod; x = (sum - y * draw) / win; if(x >= 0 && y >= 0 && x + y <= n) { printf("%lld %lld %lld\n",x,y,n-x-y); return 0; } } printf("-1\n"); return 0; }