这道题的标准解法是使用二分查找,题目给出了如何判定区间内是否有根的提示,即则在
之间一定有一个根。
但是如果借助微积分技巧,这道题还可以有另外一种解法。
首先,我们考虑若三次函数在
区间存在三个实根,那么该函数在该区间内必定存在两个顶点,即其导数
在该区间内有两个实根
,其中
,我们可以使用一元二次方程求根公式分别求出,求根公式为:
根据导数的性质,我们可以确定的三个根分别位于区间
、
和
内。于是我们可以在这三个区间内分别使用牛顿迭代法进行求根。其中牛顿迭代法公式为:
迭代的初始值可以设定为该区间的中点,一般每个区间两三次迭代即可完成。
代码如下:
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
double a, b, c, d;
const double eps = 1e-3;
double f(double x) { //求f(x)的值
return a * x * x * x + b * x * x + c * x + d;
}
double fp(double x) { //求导数f'(x)的值
return 3 * a * x * x + 2 * b * x + c;
}
double newton(double x0) { //牛顿迭代,精度为1e-3
double x = x0;
do {
x0 = x;
x = x0 - f(x0) / fp(x0);
} while (abs(x - x0) > eps);
return x;
}
int main() {
cin >> a >> b >> c >> d;
//求导数f'(x)的两个根,即函数f(x)的两个顶点
double delta = sqrt(b * b - 3 * a * c);
double xp1 = (-b - delta) / (a * 3);
double xp2 = (-b + delta) / (a * 3);
//分别对三个区间使用牛顿迭代求根
double x1 = newton(-100 + (xp1 + 100) / 2);
double x2 = newton(xp1 + (xp2 - xp1) / 2);
double x3 = newton(xp2 + (100 - xp2) / 2);
cout << fixed << setprecision(2) << x1 << " " << x2 << " " << x3;
} 
京公网安备 11010502036488号