一元三次方程求解 题解

(题目转载自洛谷)

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

输出格式
一行,3 个实根,从小到大输出,并精确到小数点后 2 位。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include<iostream>
using namespace std;
//——————————————————————法一:暴力枚举————————————————————————————

double a, b, c, d;

int main(){
scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
for(double i = -100; i <= 100; i += 0.001){
j = i + 0.001;
double y1 = a*i*i*i + b*i*i + c*i + d;
double y2 = a*j*j*j + b*j*j + c*j + d;
if(y1 * y2 <= 0) {
double x = (i + j) / 2;
printf("%.2lf", x);
}
}
return 0;
}

//——————————————————————法二:二分查找——————————————————————————————
//因为根与根之差的绝对值>=1,所以可以枚举不重叠的长度为1的区间,使用二分查找
#include<iostream>
using namespace std;

double a,b,c,d;

double f(double x){
return a*x*x*x + b*x*x + c*x + d;
}


int main(){
scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
for(double l = -100; l <= 100; l++){
double r = l + 1;
if(f(l) == 0) printf("%.2lf ", l);
if(f(l)*f(r) < 0){
double left = l, right = r;
while(right - left > 1e-4){
double mid = (left + right) / 2;
if(f(mid)*f(l) <= 0){
right = mid;
}else left = mid;
}
printf("%.2lf ", left);
}
}
return 0;
}