lanqiao3510冶炼金属 或者 acwing4956

问题:

分析:

我去年蓝桥杯做的题目,不知道做没做对,但是给的那个数据可以过,其他数据点就不知道了。

哈哈哈,当然我一开始也是猜测是不是二分,然后又想到二分要单调的,就用用二分找V,当时用的是整除的方法,也就是%,感觉也分的怪怪的。

今年我看了acwing的讲解,理解了一些东西。

1.二分的关键如何分这两部分

  • 由数据太大,不能直接暴力求解,所以通过二分的方法来找。
  • 这道题要做两次二分,分别去找最小数值,和最大数值。难点就在于求最大数值,如何来划分这个。因为Vmax对上去的B之后没有了,就到B-1了,所以要用下面这个点来分。即:search(A,B-1),而search(A,B-1)-1,再减去1是因为这个V是根据下一排来计算得到的,会比实际的V大,所以V要减去。

(图1来源于yxc讲解:AcWing 4956. 冶炼金属(春季每日一题2023) - AcWing

2.多组数据如何统一取值:

结合数学知识来理解,求共同部分,用数轴来理解

根据图2求公共部分就可以知道,求V_min要取他们的最大值,求V_max要取他们的最小值

(图2)

3.一些细节问题

因为b-1的缘故,当b=1的时候,b-1=0,那么此时search(A,B-1),而且当A=1e9时,V=1e9只B只肯等于1,所以把V=1e9+1就可以了,(yxc是这么说的:此时不管A是多少,此时B都为1,我感觉这是一个近似),但没有+1也没关系,蓝桥的测试数据也能过。

代码:

代码也是学yxc的代码,他的代码写的好简洁明了!!

小菜菜我哭了。


//二分的条件是:1.数值单调 2。由两部分的条件不一样

//这道题对1到N的所有数据进行二分。
//二分的条件看这个图 
//取max还是min根据集合(线段)来想

//求整,可以由不等式代替 
 
#include<iostream>
//lanqiao3510 acwing  4956
#include<algorithm>
#include<cstring>
using namespace std;
int N;
int A,B,V_min,V_max;

int search(int a,int b)
{
	//在l和r中寻找V,l是分母最小为1,考虑到B可能是1,所以要把V的范围稍稍整理大一点,不然容易出错 
	int l=1,r=1e9+1;
	while(l<r)
		{
			int mid=l+(r-l) /2;
			if(a/mid<=b) r=mid;   //这里用等于,见这个图 
			else l=mid+1; 
		}
		
    //找到了就返回,和上一个二分有点不一样
	return r;   //返回return r的原因还是看那个图 
}
int main() 
{
	int V_min=1,V_max=1e9;   //B在题目中有范围要大于或者等于1 
	scanf("%d",&N);
	for(int i=0;i<=N;i++)
		{
			scanf("%d%d",&A,&B);
			V_min=max(V_min,search(A,B));
		    V_max=min(V_max,search(A,B-1)-1);     //下一段的开头,所以B-1,而且V也会减去1 
		}
	printf("%d %d",V_min,V_max); 
	return 0;
}

补充:

冶炼金属【暴力枚举 + 二分 + 二元不等式】-CSDN博客

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值