[NOIP提高&洛谷P1024]一元三次方程求解 题解(二分答案)

[NOIP提高&洛谷P1024]一元三次方程求解

Description

有形如:ax3+bx2+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。

输出格式:一行,三个实根,并精确到小数点后2位。

Solution

1.考虑valid函数的写法,因为无法简单的解一元三次方程,我们不妨把方程看做函数f(x),对于自变量x,返回其对应的f(x),即:

double valid(double x){
	double num=x*x*x*a+x*x*b+x*c+d;
	return num;
} 

2.考虑因为根与根之差的绝对值>=1,在同一个宽度为1的区间内不会存在两个根,所以可以枚举-100~100之间的每一个宽度为1的区间,对每个区间进行二分;

3.对于每一个区间[L,L+1)首先判断根是否在1其中,根据零点的存在性定理,当 valid(l)* valid(l+1)≤ 0时,零点才存在于这个区间;

4.如果存在,首先检验l是否为解,若不是,二分区间,直至左右端点差值满足精度要求为止;

5.注意:因为我们枚举的是区间[L,L+1),所以100没有被检验过,最后记得检验100是否为根;

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

int i,j,k;
double l,r,mid,a,b,c,d;

double valid(double x){
	double num=x*x*x*a+x*x*b+x*c+d;
	return num;
} 

int main(){
	scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
	for(i=-100;i<100;++i)
		if(valid(i)==0)printf("%.2lf ",(double)i);
		else if(valid(i)*valid(i+1)<0){
			l=i;r=l+1;
			while(r-l>=0.001){
				mid=(l+r)/2;
				if(valid(l)*valid(mid)<=0)r=mid;
				else l=mid;
			}
			printf("%.2lf ",l);
		}
        if(valid(100)==0)printf("100.00");
	printf("\n");
	return 0;
}

二分答案的基础参考以前的随笔:http://www.cnblogs.com/COLIN-LIGHTNING/p/8543330.html

posted @   COLINGAO  阅读(997)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示