二元一次方程问题

51nod1548 欧姆诺和糖果

题面:有A和B两种物品,每件A花费Wa,收益Ha,每件B花费Wb,收益Hb,要求总花费不超过C(<=1e9),求最大收益。

分析:不妨设物品A的性价比更高(如不满足交换二者即可),那么Ha/Wa>=Hb/Wb,即Ha*Wb>=Hb*Wa。考虑Wb件A物品与Wa件B物品,因为Wb*Wa=Wa*Wb,故而它们的花费是一样的,但收益却有高低,因为Ha*Wb>=Hb*Wa,因此将Wa件B物品换成Wb件A物品是更优的选择,至少不会更差。根据这条性质,用反证法容易证明,取到最优值时,性价比低的物品数肯定不会超过sqrt(C),从而得到了sqrt(n)时间复杂度的枚举法。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL c, hr, hb, wr, wb, ans;
int main() {
    cin >> c >> hr >> hb >> wr >> wb;
    for (LL i = 0; i * i <= c; i++) {
        if (i * wr <= c)
            ans = max(ans, hr*i + (c-wr*i)/wb*hb);
        if (i * wb <= c)
            ans = max(ans, hb*i + (c-wb*i)/wr*hr);
    }
    cout << ans << endl;
    return 0;
}

51nod1352 集合计数

题面:给定int32范围内的正整数A,B,C,问方程Ax+By=C有多少组正整数解(x,y)?

分析:根据扩展欧几里德算法判断方程是否有解,如有则求出一组解(x0,y0),那么通解可表示为(x0+kB,y0-kA),统计正整数解即可。需要注意的是用扩展欧几里德算法求出解的特征,|x0|+|y0|最小,且系数绝对值大的那项绝对值小。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL gcd(LL a, LL b) {
    return b ? gcd(b, a%b) : a;
}
void exgcd(LL a, LL &x, LL b, LL &y) {
    if (b == 0) {
        x = 1; y = 0;
    } else {
        exgcd(b, y, a%b, x);
        y -= a/b*x;
    }
}
LL T, n, a, b, d, k, x, y, z, ans;
int main() {
    ios::sync_with_stdio(0);
    cin >> T;
    while (T--) {
        cin >> n >> a >> b;
        d = gcd(a, b);
        if ((n+1) % d) {
            ans = 0;
        } else {
            a /= d; b /= d; k = (n+1) / d;
            exgcd(a, x, b, y);   // ax + by = 1
            x *= k; y *= k;      // ax + by = k
            ans = x/b + y/a;
            if (x > 0 && x % b == 0) ans -= 1;
            if (y > 0 && y % a == 0) ans -= 1;
        }
        cout << ans << endl;
    }
    return 0;
}

其中,ans -= 1那两行最多只有一行满足条件。

Table of Contents