一元三次方程求解 | 刷题打卡

306 阅读1分钟

本文正在参与掘金团队号上线活动,点击查看大厂春招职位

一、题目描述

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

提示:

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

输入格式 一行,44 个实数 a, b, c, d。

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

输入输出样例

输入
1 -5 -4 20
输出
-2.00 2.00 5.00

【题目来源】

NOIP 2001 提高组第一题

二、思路分析

这道题我首先用二分查找做了一遍,因为实根之间差的绝对值大于1,所以就在-100到100之间每个整数的区间内二分查找,找不出就返回101(本来想找不出就结束函数的,但不知道怎么写),找出实根就返回,不写f(right)==0的情况是因为向右查找时会重复,比如,如果4是解Binarysearch(3,4)会输出4, Binary(4,5)也会输出4
只能过一半测试点,现在都没发现哪错了😢,测试点 输入1 -4.65 2.25 1.4
正确输出:-0.35 1.00 4.00 我的输出:0.00 1.00 4.50
有大佬能看看我哪错了嘛?
我用暴力又做了一遍......,本来是直接全部枚举的,后来加了个break,找出3个实根就结束运行了,缩短了点运行时间

三、AC代码

法一:暴力枚举----出奇迹

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n=0;
	double a,b,c,d; 
	cin>>a>>b>>c>>d;
	for(double i=-100;i<=100;i+=0.001)
	{
		if(fabs(a*i*i*i+b*i*i+c*i+d)<0.001)
			printf("%.2lf ",i),n++;
		if(n==3) break;	 
	}
	return 0;
}

法二;二分查找(只对了一半......)

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
double a,b,c,d;
double f(double x)
{
	return a*x*x*x+b*x*x+c*x+d;
}
double Binarysearch(double left,double right)
{
	double mid=left+(right-left)/2;
	if(right-left<0.001)
		return left;
	else if(f(mid)==0) return mid;
            else if(f(left)==0) return left;
		 else if(f(left)*f(mid)<0) return(left,mid);//零点在左半部分 
                     else if(f(mid)*f(right)<0) return(mid,right);//零点在右半部分 
	else return 101;
}
int main()
{
	double result;
	cin>>a>>b>>c>>d;
	for(double i=-100;i<100;i++)
		if(Binarysearch(i,i+1)!=101)
			printf("%.2f ",Binarysearch(i,i+1));
	return 0;
}

四、总结

代码不停
掘金不止
今天有比昨天编程时间多一点😜
放开手脚大干一场吧,少年!
ps:下次用公式法再解一遍