题目传送门:一元三次方程求解
盛金公式
$part \texttt{1.}$ 基本概念
- 根:方程的解。
- 实根:指方程式的解为实数解。实数包括正数,负数和 $0$。
$part \texttt{2.}$ 一元三次方程的一般形式
$$ax^3+bx^2+cx+d=0\left(a\neq0\right).$$
$part \texttt{3.}$ 一元三次方程的实根
令 $x=y-\dfrac{b}{3a}$,则
$$a\left(y-\dfrac{b}{3a}\right)^3+b\left(y-\dfrac{b}{3a}\right)^2+c\left(y-\dfrac{b}{3a}\right)+d=0$$
$$a\left(y^3-\dfrac{by^2}{a}+\dfrac{b^2y}{3a^2}-\dfrac{b^3}{27a^3}\right)+b\left(y^2-\dfrac{2by}{3a}+\dfrac{b^2}{9a^2}\right)+c\left(y-\dfrac{b}{3a}\right)+d=0$$
$$ay^3-by^2+\dfrac{b^2}{3a}y-\dfrac{b^3}{27a^2}+by^2-\dfrac{2b^2}{3a}y+\dfrac{b^3}{9a^2}+cy-\dfrac{bc}{3a}+d=0$$
$$ay^3+\left(c-\dfrac{b^2}{3a}\right)y+\left(d+\dfrac{2b^3}{27a^2}-\dfrac{bc}{3a}\right)=0$$
$$y^3+\left(\dfrac{c}{a}-\dfrac{b^2}{3a^2}\right)y+\left(\dfrac{d}{a}+\dfrac{2b^3}{27a^3}-\dfrac{bc}{3a^2}\right)=0$$
令 $p=\dfrac{c}{3a}-\dfrac{b^2}{9a^2}$,$q=\dfrac{d}{2a}+\dfrac{b^3}{27a^3}-\dfrac{bc}{6a^2}$,则
$$y^3+3py+2q=0$$
令 $\Delta=q^2+p^3$,则
$\left(1\right)$ 当 $\Delta>0$ 时,方程只有一个实根:
$$y=\sqrt[3]{-q+\sqrt{\Delta}}+\sqrt[3]{-q-\sqrt{\Delta}}$$
$\left(2\right)$ 当 $\Delta=0$ 时,方程有三个实根,其中至少有两个相等的实根:
$$y_1=-2\sqrt[3]{q}$$
$$y_2=y_3=\sqrt[3]{q}$$
$\left(3\right)$ 当 $\Delta<0$ 时,方程有三个不等实根:
$\quad \ \ $令 $\alpha=\dfrac{1}{3}\arccos\dfrac{-q\sqrt{-p}}{p^2}$,则
$$y_1=2\sqrt{-p}\cos\alpha$$
$$y_2=2\sqrt{-p}\cos\left(\alpha+120^\circ\right)$$
$$y_3=2\sqrt{-p}\cos\left(\alpha+240^\circ\right)$$
$part \texttt{4.}$ 代码实现
// 除一元三次方程外,附上一元一次方程与一元二次方程的实根求解代码
#include <bits/stdc++.h>
using namespace std;
// #define int long long
const double PIE = 3.1415926535897932384626433832795;
static double SolveCubicRoot(double value); // 立方根
static void SolveLinearEquation(double a, double b); // 一元一次方程
static void SolveQuadraticEquation(double a, double b, double c); // 一元二次方程
static void SolveCubicEquation(double a, double b, double c, double d); // 一元三次方程
int op;
double A, B, C, D;
vector<double> root;
// 求一个实数的立方根
double SolveCubicRoot(double value) {
return value > 0 ? pow(value, 1.0 / 3) : -pow(-value, 1.0 / 3);
}
// 求一元一次方程的实根
void SolveLinearEquation(double a, double b) {
if (a != 0) // 判断一次项系数是否为零
root.push_back(-b / a);
return;
}
// 求一元二次方程的实根
void SolveQuadraticEquation(double a, double b, double c) {
if (a == 0) { // 判断二次项系数是否为零
SolveLinearEquation(b, c);
return;
}
double delta = b * b - 4 * a * c; // 判别式
if (delta > 0) { // 方程有两个不等的实根
root.push_back((-b + sqrt(delta)) / (2 * a));
root.push_back((-b - sqrt(delta)) / (2 * a));
} else if (delta == 0) // 方程有两个相等的实根
root.push_back(-b / (2 * a));
return;
}
// 求一元三次方程的实根
void SolveCubicEquation(double a, double b, double c, double d) {
if (a == 0) { // 判断三次项系数是否为零
SolveQuadraticEquation(b, c, d);
return;
}
double p = (c / a - b * b / (3 * a * a)) / 3;
double q = (d / a + 2 * b * b * b / (27 * a * a * a) - b * c / (3 * a * a)) / 2;
double diff = -b / (3 * a);
double delta = p * p * p + q * q; // 判别式
if (delta > 0) { // 方程只有一个实根
double sqrtDelta = sqrt(delta);
root.push_back(SolveCubicRoot(-q + sqrtDelta) + SolveCubicRoot(-q - sqrtDelta));
} else if (delta < 0) { // 方程有三个不等的实根
double angle = acos(-q * sqrt(-p) / (p * p)) / 3;
root.push_back(2.0 * sqrt(-p) * cos(angle));
root.push_back(2.0 * sqrt(-p) * cos(angle + 2 * PIE / 3));
root.push_back(2.0 * sqrt(-p) * cos(angle + 4 * PIE / 3));
} else { // 方程有三个实根,其中至少有两个相等的实根
if (q == 0) root.push_back(0);
else {
root.push_back(SolveCubicRoot(q));
root.push_back(-2 * SolveCubicRoot(q));
}
}
for (int i = 0, maxSize = root.size(); i < maxSize; ++i)
root[i] += diff; // 将结果加上余量
return;
}
// 排序并打印结果
void print() {
priority_queue<double, vector<double>, greater<double> > q;
int cnt = 0;
for (auto i : root) {
q.push(i);
cnt++;
}
while (cnt--) {
cout << fixed << setprecision(2) << q.top() << " ";
// 保留两位小数,也可以用 printf 的 %.2f
q.pop(); // 记住一定要 pop
}
cout << "\n";
}
signed main() {
cin >> op;
if (op == 1) { // 一元一次方程
cin >> A >> B;
SolveLinearEquation(A, B);
print();
} else if (op == 2) { // 一元二次方程
cin >> A >> B >> C;
SolveQuadraticEquation(A, B, C);
print();
} else { // 一元三次方程
cin >> A >> B >> C >> D;
SolveCubicEquation(A, B, C, D);
print();
}
return 0;
}
正解提交结果
代码不是题目的正解,会有小改动,学习后自己敲哦
PS: 如有错误请在聊天区 @ 我哦