★P1024 [NOIP 2001 提高组] 一元三次方程求解

题目描述

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

提示:记方程 f(x)=0,若存在 2 个数 x1x2,且 x1<x2f(x1)×f(x2)<0,则在 (x1,x2) 之间一定有一个根。

输入格式

一行,4 个实数 a,b,c,d

输出格式

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

输入输出样例 #1

输入 #1

1 -5 -4 20

输出 #1

-2.00 2.00 5.00

说明/提示

【题目来源】

NOIP 2001 提高组第一题

题解

#include <bits/stdc++.h>
using namespace std;
double a, b, c, d;
vector<double> roots;
double f(double x) {
return a*x*x*x + b*x*x + c*x + d;
}
// 本题有一个测试点会重复计入根,当一个端点(例如 i 或 i+1)正好满足 f(x) ≈ 0 时,代码会先直接把这个端点加入根列表;随后在同一个区间,二分法又找到了一个近似相同的根,导致重复计入,这里添加判断防止重复,在每次加入新根前,可以判断当前新根与已存在根的距离是否足够大(如大于 1e-6),如果非常接近则跳过。
bool isNewRoot(double x) {
for (double r : roots) {
if (fabs(r - x) < 1e-6)
return false;
}
return true;
}
void search() {
for (double i = -100; i < 100; i++) {
double left = i, right = i + 1;
// 判断端点是否为根
if (fabs(f(left)) < 1e-6 && isNewRoot(left)) {
roots.push_back(left);
if (roots.size() == 3) break;
continue; // 跳过本次区间的二分,防止重复计入
}
if (fabs(f(right)) < 1e-6 && isNewRoot(right)) {
// 如果右端点是根,先尝试二分法,避免重复
if (f(left)*f(right) < 0) {
// 二分求根
while (right - left > 1e-7) {
double mid = left + (right - left) / 2;
if (f(mid) * f(left) < 0)
right = mid;
else
left = mid;
}
double root = (left + right) / 2;
if (isNewRoot(root)) {
roots.push_back(root);
if (roots.size() == 3) break;
}
} else {
// 如果区间内没有符号变化,则直接添加右端点
roots.push_back(right);
if (roots.size() == 3) break;
continue;
}
}
// 对于一般情况,判断区间内是否有根
if (f(left) * f(right) < 0) {
while (right - left > 1e-7) {
double mid = left + (right - left) / 2;
if (f(mid) * f(left) < 0)
right = mid;
else
left = mid;
}
double root = (left + right) / 2;
if (isNewRoot(root)) {
roots.push_back(root);
if (roots.size() == 3) break;
}
}
}
}
int main() {
cin >> a >> b >> c >> d;
search();
sort(roots.begin(), roots.end());
for (size_t i = 0; i < roots.size(); i++) {
if (i > 0) cout << " ";
printf("%.2lf", roots[i]);
}
cout << endl;
return 0;
}
发布于   xiins  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示