题目
小蓝有一个神奇的炉子用于将普通金属 O 冶炼成为一种特殊金属 X。这个炉子有一个称作转换率的属性 V,V 是一个正整数,这意味着消耗 V 个普通金属 O 恰好可以冶炼出一个特殊金属 X,当普通金属 O 的数目不足 V 时,无法继续冶炼。现在给出了 N 条冶炼记录,每条记录中包含两个整数 A 和 B,这表示本次投入了 A 个普通金属 O,最终冶炼出了 B 个特殊金属 X。每条记录都是独立的,这意味着上一次没消耗完的普通金属 O 不会累加到下一次的冶炼当中。
根据这 N 条冶炼记录,请你推测出转换率 V 的最小值和最大值分别可能是多少,题目保证评测数据不存在无解的情况。
输入输出
输入:第一行一个整数 N,表示冶炼记录的数目。接下来输入 N 行,每行两个整数 A、B,含义如题目所述。
输出:输出两个整数,分别表示 V 可能的最小值和最大值,中间用空格分开。
题解
这题就是A是金额,V是价格,B是购买数量。根据每组A和B来求出V的范围。
直观思路就是对于每组A和B,求出V的范围,然后取每组V的范围的交集。
所以关键就是求每组范围,易知 V*B <= A,所以确定了 V <= A/B。然后就是确定V的左区间,通过临界情况来求。临界情况是B+1 = A/V,这种情况是临界且不满足题目要求的。所以就可以得到V的左区间 V 不等于A / (B+1) 。所以V的区间是(A/(B+1), A/B],相当于[A/(B+1)+1, A/B]。
求出区间就很好弄了,维护一个最大最小值。遍历每组的区间,如果左边界大于最小值,就更新最小值;边界小于最大值,就更新最大值。最后的交集就是最小值和最大值。
代码
int main()
{
int max = 1e9 + 1; // 比题目的最大输入数据大一点
int min = 0;
int a, b, line; // line是输入的行数
cin >> line;
for (int i = 0; i < line; i++)
{
cin >> a >> b;
int left = a/(b+1) + 1; // V的左区间
int right = a / b; // V的右区间
if (left > min)
min = left;
if (right < max)
max = right;
}
cout << min << ' ' << max;
return 0;
}