洛谷P1024[NOIP2001 提高组] 一元三次方程求解(cpp)(二分查找)

该文章详细阐述了如何通过二分查找法解决一元三次方程的实根问题,涉及导数的应用,以及C++代码实现中的关键步骤
摘要由CSDN通过智能技术生成

目录

1.题目

2.思路

3.AC


1.题目

# [NOIP2001 提高组] 一元三次方程求解

## 题目描述

有形如:ax^{3}+bx^{2}+cx+d=0  这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在 -100 至 100 之间),且根与根之差的绝对值 大于等于1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后 2 位。

提示:记方程 f(x) = 0,若存在 2个数 x1 和 x2,且 x1 < x2,f(x1) × f(x2) < 0,则在 (x1, x2) 之间一定有一个根。

## 输入格式

一行,4 个实数 a, b, c, d。

## 输出格式

一行,3 个实根,从小到大输出,并精确到小数点后 2 位。

## 样例 #1

### 样例输入 #1

```
1 -5 -4 20
```

### 样例输出 #1

```
-2.00 2.00 5.00
```

## 提示

**【题目来源】**

NOIP 2001 提高组第一题

2.思路

①a>0时,若 ax^{3}+bx^{2}+cx+d=0 有三个实根,则图像为

图像与x轴的三个交点即为方程的三个根。将方程化为三个区间〔-100,t1〕,〔t1,t2〕,〔t2,100〕,利用二分查找就可以得到答案!

②如何得到t1,t2的值?对原方程求导,得到的导函数为y=3ax^{2}+2bx+c,图像为

将方程化为两个区间〔-100,t0〕,〔t0,100〕,再利用二分查找!

③如何求t0?对函数再求导,使导函数为0,得t0 = -\frac{b}{3a}

3.AC

#include <iostream> 
#include <cstdio>
using namespace std;

int main () {
	double a, b, c, d, q[3];
	scanf("%lf%lf%lf%lf", &a, &b, &c, &d);

    //保证a>0
	if (a < 0) {
		a *= -1;
		b *= -1;
		c *= -1;
		d *= -1;
	}

    //求t0
	double t0 = -b/(3*a);

    //求t1
	double l = -100, r = t0;
	while (r - l > 1e-4) {
		double mid = (l+r)/2;
		if (3*a*mid*mid + 2*b*mid +c >= 0) l = mid;
		else r = mid;
	}
	double t1 = l;

	//求t2
	l = t0, r = 100;
	while (r - l > 1e-4) {
		double mid = (l+r)/2;
		if (3*a*mid*mid + 2*b*mid +c >= 0) r = mid;
		else l = mid;
	}
	double t2 = l;
	
    //求三个根
	l = -100, r = t1;
	while (r - l > 1e-4) {
		double mid = (l+r)/2;
		if (a*mid*mid*mid + b*mid*mid +c*mid + d >= 0) r = mid;
		else l = mid;
	}
	printf("%.2lf ", l);
	
	l = t1, r = t2;
	while (r - l > 1e-4) {
		double mid = (l+r)/2;
		if (a*mid*mid*mid + b*mid*mid +c*mid + d >= 0) l = mid;
		else r = mid;
	}
	printf("%.2lf ", l);
	
	l = t2, r = 100;
	while (r - l > 1e-4) {
		double mid = (l+r)/2;
		if (a*mid*mid*mid + b*mid*mid +c*mid + d >= 0) r = mid;
		else l = mid;
	}
	printf("%.2lf", l);

	return 0;
}

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值