蓝桥杯真题 - 冶炼金属 - 题解

题目链接:https://www.lanqiao.cn/problems/3510/learning/

个人评价:难度 2 星(满星:5)
前置知识:二分


整体思路

  • 二分得到满足条件的最大值与最小值,这里以二分最大值为例(最小值同理):
  • 如果“满足条件”,就提高下界,否则降低上界,最终答案为下界(因为下界是满足条件的那一个);
  • 所有小于等于下界的都应该认为是“满足条件”的,这里的条件是指:对于任意 i ∈ [ 1 , n ] i \in [1, n] i[1,n] 都有 ⌊ A i m i d ⌋ ≥ B i \lfloor \frac{A_i}{mid} \rfloor \geq B_i midAiBi
  • 二分的初始下界为 1 1 1,因为如果转化率为 0 0 0,则 B i B_i Bi 就有可能为 0 0 0,但所有的 B i B_i Bi 都大于等于 1 1 1,二分的初始上界为 min ⁡ ( A i )   i ∈ [ 1 , n ] \min(A_i)~i \in [1, n] min(Ai) i[1,n],但由于所有大于等于 min ⁡ ( A i ) \min(A_i) min(Ai) 的上界也能通过二分正确判断是否满足条件,所以代码里直接取 A 1 A_1 A1 作为上界也能得到正确结果。

过题代码

#include 
using namespace std;

typedef long long LL;
const int maxn = 10000 + 100;
int n;
int a[maxn], b[maxn];

bool judgeMin(int mid) {
    for (int i = 0; i < n; ++i) {
        if (a[i] / mid > b[i]) {
            return false;
        }
    }
    return true;
}

int findMin() {
    int low = 0;
    int high = a[0];
    int mid;
    while (high - low > 1) {
        mid = (high + low) >> 1;
        if (judgeMin(mid)) {
            high = mid;
        } else {
            low = mid;
        }
    }
    return high;
}

bool judgeMax(int mid) {
    for (int i = 0; i < n; ++i) {
        if (a[i] / mid < b[i]) {
            return false;
        }
    }
    return true;
}

int findMax() {
    int low = 1;
    int high = a[0] + 1;
    int mid;
    while (high - low > 1) {
        mid = (high + low) >> 1;
        if (judgeMax(mid)) {
            low = mid;
        } else {
            high = mid;
        }
    }
    return low;
}

int main() {
#ifdef ExRoc
    freopen("test.txt", "r", stdin);
#endif // ExRoc
    ios::sync_with_stdio(false);

    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> a[i] >> b[i];
    }
    cout << findMin() << " " << findMax() << endl;

    return 0;
}

你可能感兴趣的:(蓝桥杯,c++,算法)