【算法每日一练]-二分精确 篇4 kotori的设备 ,银行贷款 ,一元三次方程求解

本文介绍了如何使用二分查找算法解决三个问题:设备最长使用时间的精确计算、银行贷款月利率的确定以及一元三次方程的解。通过二分法找到最优解,确保精度并简化计算过程。

今天讲二分精确题型

目录

题目:kotori的设备

 思路:

题目:银行贷款

 思路:

 题目:一元三次方程求解

  思路:


    

       

题目:kotori的设备

       

 思路:

     

求:设备最长使用时间
二分查找:对使用时间进行二分查找
二分依据:该时间可提供的能量(对比该时间需要补充的能量,若超过则增加时间找最优解)  

     

#include <iostream>              
using namespace std;
int n;
double sum,p,l=0,r=1e10;
double a[200000],b[200000];
int check(double ans){   
	double q=p*ans;//这个时间可提供的能量
	sum=0;
	for(int i=0;i<n;i++){
		if(a[i]*ans<=b[i]) 	continue;//设备在该时间内不需要充电
		sum+=(a[i]*ans-b[i]);//否则就计算还需要的额外能量
	}
	return sum<=q;//需要的能量小于等于充电器提供的,则这个时间可以做解
}
int main(){
	cin>>n>>p;
	for(int i=0;i<n;i++){
		cin>>a[i]>>b[i];
		sum+=a[i];
	}
	if(sum<=p){   //若所有设备的消耗能量速度总和还是小于充电器的充电速度,输出-1。
		cout<<-1.000000<<endl;
		return 0;
	}
	while(r-l>1e-6){     //和标准答案相差小于10e-4即可
		double mid=(l+r)/2;
		if(check(mid))  l=mid;//如果mid可以做解,就向右逼近
		else	r=mid;      //如果不能做解,就向左找解
	}
	cout<<l<<endl;
//二分精确就简单多了,r-l控制好精度,到时候就不需要管=在哪里,不需要管输出l,r,mid
	return 0;
}

      

        

题目:银行贷款

       

思路:

       

题意就是在换完每月的钱后,到12月时钱恰好为pay*mon,也就是loan=loan*(1+ans)-pay经过12次循环后为0或逼近0

     
求:月利率
二分查找:对利率进行二分查找(二分精确)
二分依据:该利率下12个月后的贷款
    

#include <iostream>            
#include <cstdio>
using namespace std;
int main(){
	int loan,pay,mon;
	double l=0,r=10,mid,t;            //利率可能大于1
	cin>>loan>>pay>>mon;
	while(r-l>0.0001){                    
		mid=(l+r)/2;
		t=loan;
		for(int i=0;i<mon;i++){
			t=t*(1+mid)-pay;
		}
		if(t>0) r=mid;           //t大于0说明利率太大了,那就调小利率
		else if(t<0) l=mid;
		     else{
		     	printf("%.1f",mid*100);  //(找理想解)可以直接输出
		     	return 0;
			 }
	}
	printf("%.1f",mid*100);  //保留小数点后一位
	return 0;
}

       

      

 题目:一元三次方程求解

      

思路:

    
二分查找:对解进行二分
二分依据:零点定理
     

#include<cstdio>              
double a,b,c,d;
double f(double x)                 //输入自变量,返回函数值
{
    return a*x*x*x+b*x*x+c*x+d;
}
int main()
{
    double l,r,mid,x1,x2;
    int ans=0,i;               //ans是答案个数
    scanf("%lf%lf%lf%lf",&a,&b,&c,&d);  
    for (i=-100;i<100;i++)
    {
        l=i; r=i+1; x1=f(l); x2=f(r);   //将每个i分成[i,i+1]区间,然后处理f(i)和f(i+1)符号
        if(x1==0)                     //若i刚好命中就输出(即左端点i刚好是零点)
        {
            printf("%.2lf ",l);     ans++;   //不能判断右端点,会重复
        }      
        if(x1*x2<0)                          //根落在区间时就二分查找
        {
            while(r-l>=0.001)//控制精度                   
            {
                mid=(l+r)/2;  
                if(f(mid)*f(r)<=0)    l=mid;   //向右压缩
                else    r=mid;                 //向左压缩
            }
            printf("%.2lf ",r);            //左右都可以
            ans++;
        }
        if (ans==3)  break;             
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值