本文正在参与掘金团队号上线活动,点击查看大厂春招职位
一、题目描述
有形如: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:下次用公式法再解一遍