先看一下什么叫转换率的最小值和最大值,看其样例
投入75个o,产出3个x
53个o,换2个x
59个o,换2个x
得出最少20个o换一个x;最多25个o换一个x
也就是说用不同的投入值除以一个相同的数字得到其对应的产出值
而这个相同的数字有多个,在这里面找到头和尾,最大值和最小值。
在实在不会的情况下,可以将投入值和产出值分别输入上下取整的式子中
这里我们用到的方法是二分查找法
二分查找法不一定是要去找,它是有单调性的
我们已经知道它会有2个答案解的,min和max。边界为min>=1;max<=A<=10^9
Bi就是min到max这一整段数据
在这半段对Ai的要求增加时,在o总数不变的情况下,产出x是变少降低的。
也就是转换率V降低了,此时V<Bi
同理,当对Ai的要求减少时,可以取个极端的例子,1个o就可以置换出1个x,那Bi就很大了,那V就是100%了
此时V>Bi
则max在这段找
min在这儿找
二分查找法不一定是要去找,它是有单调性的,只要这半边符合它的性质
而这道题可以分成2个二分查找
这里的V是我们假定出来的答案,我们要做的就是试一试这个V符不符合题目要求
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include<math.h>//+ —*/都要用
const int MAX_N = 1e4 + 1;//数据最大值范围
int N, A[MAX_N], B[MAX_N];//要输入的数据
bool check_min(int v)
{
for (int i = 1; i <= N; i++)
{
if ((A[i] / v) > B[i])//蓝线之外的max
return false;
}
return true;
}
bool check_max(int v)
{
for (int i = 1; i <= N; i++)
{
if ((A[i] / v) < B[i])//红线之外的min,多重运算带()
return false;
}
return true;
}
int main()
{
// 请在此输入您的代码
scanf("%d", &N);
for (int i = 1; i <= N; i++)
{
scanf("%d%d", &A[i], &B[i]);
}
int l = 1, R = 1000000000, V_min;//先找最小值,范围1~R
while (l <= R)
{
int mid = (l + R) / 2;//==(l+R)>>1
if (check_min(mid))//找最小值,则让右边端点往左边缩小移
{
V_min = mid;//符合要求,在min和max之间的
R = mid - 1;//末尾左移
}
else
l = mid + 1;//首位右移
l = 1, R = 1000000000;
int V_max;//再找最大值,范围1~R int V_max;要单独写
while (l <= R)
{
int mid = (l + R) / 2;//折半找中间
if (check_max(mid))//找最大值,则让左边端点往右边缩小移
{
V_max = mid;
l = mid + 1;//左首右移
}
else
R = mid - 1;//右末左移
}
printf("%d%d", V_min, V_max);
}
//printf("%d%d", V_min, V_max);//记得V_max的作用区域,即看{ }
return 0;
}
可以看到这个代码块——求最小值的地方出错了;且没有空格间隔
这里最小值直接输出这个了(有可能是花括号的问题)
现在对了
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include<math.h>//+ —*/都要用
const int MAX_N = 1e4 + 1;//数据最大值范围
int N, A[MAX_N], B[MAX_N];//要输入的数据
bool check_min(int v)
{
for (int i = 1; i <= N; i++)
{
if ((A[i] / v) > B[i])//蓝线之外的max
return false;
}
return true;
}
bool check_max(int v)
{
for (int i = 1; i <= N; i++)
{
if ((A[i] / v) < B[i])//红线之外的min,多重运算带()
return false;
}
return true;
}
int main()
{
// 请在此输入您的代码
scanf("%d", &N);
for (int i = 1; i <= N; i++)
{
scanf("%d%d", &A[i], &B[i]);
}
int l = 1, R = 1000000000, V_min;//先找最小值,范围1~R
//2个while循环分开
while (l <= R)
{
int mid = (l + R) / 2;//==(l+R)>>1
if (check_min(mid))//找最小值,则让右边端点往左边缩小移
{
// int mid = (l + R) / 2;//==(l+R)>>1
V_min = mid;//符合要求,在min和max之间的
R = mid - 1;//末尾左移
}
else
l = mid + 1;//首位右移
}
l = 1, R = 1000000000;
int V_max;//再找最大值,范围1~R int V_max;要单独写
while (l <= R)
{
int mid = (l + R) / 2;//折半找中间
if (check_max(mid))//找最大值,则让左边端点往右边缩小移
{
V_max = mid;
l = mid + 1;//左首右移
}
else
R = mid - 1;//右末左移
}
printf("%d %d", V_min, V_max);
//printf("%d%d", V_min, V_max);//记得V_max的作用区域,即看{ }
return 0;
}