codeforces 1244C (thinking or extended Euclidean)

(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;
}
View Code

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;
}
View Code

Guess you like

Origin www.cnblogs.com/winter-bamboo/p/11723600.html