拓展欧几里得算法,ExGCD

exgcd用于计算,形如ax+by=c的解。

证明:参考:https://www.cnblogs.com/mrclr/p/9380300.html

1、利用exgcd求解ax0+by0=gcd(a,b)的一个解:

LL ExGCD(LL a, LL b, LL &x, LL &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    LL xx, yy;
    LL gcd = ExGCD(b, a % b, xx, yy);
    x = yy;
    y = xx - yy * (a / b);
    return gcd;
}
View Code

此函数返回值为gcd(a,b),x和y即为ax0+by0=gcd(a,b)的一个解

2、此时,可以得到ax+by=c的一个解:x1=x0*(c/gcd(a,b)),y1=y0*(c/gcd(a,b))

3、可以有结论,若要ax+by=c存在整数解,当且仅当c/gcd(a,b)为整数,即需要(gcd(a,b)|c)

4、可以得到,对于ax+by=c,令:x1=x0*(c/gcd(a,b)),y1=y0*(c/gcd(a,b)),

5、可得解集:

{(x, y) | x = x1 + k * b / gcd(a, b), y = y1 - k * a / gcd(a, b), k ∈ z}

 

例题:

https://codeforces.ml/contest/1728/problem/E

代码:

#include<bits/stdc++.h>

#define fore(x,y,z) for(LL x=(y);x<=(z);x++)
#define forn(x,y,z) for(LL x=(y);x<(z);x++)
#define rofe(x,y,z) for(LL x=(y);x>=(z);x--)

#define all(x) (x).begin(),(x).end()
#define fi first
#define se second

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
PLL ab[300010];
LL psuma[300010];
LL psumb[300010];

LL ExGCD(LL a, LL b, LL & x, LL & y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    LL xx, yy;
    LL gcd = ExGCD(b, a % b, xx, yy);
    x = yy;
    y = xx - yy * (a / b);
    return gcd;
}
void YD()
{
    int n; cin >> n;
    fore(i, 1, n) cin >> ab[i].first >> ab[i].second;
    sort(ab + 1, ab + n + 1, [](PLL& x, PLL& y) { return x.first - x.second > y.first - y.second; });
    for (int i = 1; i <= n; i++)
    {
        psuma[i] = psuma[i - 1] + ab[i].first;
        psumb[i] = psumb[i - 1] + ab[i].second;
    }
    int idx = 0;
    for (int i = 1; i <= n; i++)
    {
        if (ab[i].first - ab[i].second < 0)
        {
            idx = i;
            break;
        }
    }
    if (idx == 0) idx = n + 1;
    int cnta = idx-1;
    int cntb = n-cnta;
    int q;
    cin >> q;
    while (q--)
    {
        LL a, b; cin >> a >> b;
        LL x, y;
        LL gcd = ExGCD(a, b, x, y);
        if (n % gcd != 0)
        {
            cout << -1 << endl;
            continue;
        }
        x = x * n / gcd;
        y = y * n / gcd;
        double kd = (double(cnta) / a - x) * gcd / b;
        LL k = kd;
        LL k1 = k - 1,k2=k,k3=k+1;
        LL x1 = x + k1 * b / gcd, x2 = x + k2 * b / gcd, x3 = x + k3 * b / gcd;
        LL y1 = y - k1 * a / gcd, y2 = y - k2 * a / gcd, y3 = y - k3 * a / gcd;
        LL a1 = a * x1, a2 = a * x2, a3 = a * x3;
        LL b1 = b * y1, b2 = b * y2, b3 = b * y3;
        LL res1 = (a1 >= 0 && b1 >= 0) ?(psuma[a1]+psumb[n]-psumb[n-b1]) : -1;
        LL res2 = (a2 >= 0 && b2 >= 0) ? (psuma[a2] + psumb[n] - psumb[n - b2]) : -1;
        LL res3 = (a3 >= 0 && b3 >= 0) ? (psuma[a3] + psumb[n] - psumb[n - b3]) : -1;
        LL max_res = max({ res1, res2, res3 });
        cout << max_res << endl;
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T = 1;
    //cin >> T;
    while (T--)
    {
        YD();
    }
    return 0;
}
View Code

 

posted @ 2022-09-10 11:28  80k  阅读(20)  评论(0编辑  收藏  举报