洛谷-P1024 [NOIP2001 提高組] 一元三次方程求解
阿新 • • 發佈:2021-07-10
題目描述
有形如:a x^3 + b x^2 + c x + d = 0這樣的一個一元三次方程。給出該方程中各項的係數(a,b,c,d均為實數),並約定該方程存在三個不同實根(根的範圍在-100至100之間),且根與根之差的絕對值≥1。要求由小到大依次在同一行輸出這三個實根(根與根之間留有空格),並精確到小數點後2位。
提示:記方程f(x)=0,若存在22個數x1和x2,且x1<x2, f(x1)×f(x2)<0,則在 (x1,x2)之間一定有一個根。
輸入格式
一行,44個實數a, b, c, d。
輸出格式
一行,33個實根,從小到大輸出,並精確到小數點後22位。
輸入輸出樣例
輸入#1 |
輸出#1 |
1 -5 -4 20 |
-2.00 2.00 5.00 |
題目分析
- 方程求解時,計算機一般採用二分法去不斷逼近方程的解,當二分割槽間小於某個精度的時候我們就可以近似的認為該區間的中間值為方程的解。
- 根據題目所給資訊,三個根的範圍一定是在(-100, 100),並且任意兩個根的絕對值之差大於1,可知:根的總範圍為(-100, 100)且最小尋找區間長度為1。我們只需要從-100開始以1為區間長度,不斷判斷區間內是否有根。
- 注意:二分查詢時是否查每個小區間的邊界,本文程式碼是查了雙邊界的,但是由於解如果在邊界就會重複,注意去重。
可行程式碼
#include <algorithm> #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; } // f(x) double search(double l, double r) { double mid; bool flag = true; for (int i = 0; i <= 2000; i++) { mid = (l + r) / 2.0; if (f(l) * f(mid) <= 0) r = mid; else if (f(r) * f(mid) <= 0) l = mid; else { flag = false;// 查到結果直接返回 break; } } if (flag) return mid; return -1000;// 根不在區間(l, r) } int main() { cin >> a >> b >> c >> d; double X[3]; int cnt = 0; for (int i = -100; i <= 100; i++) { double x = search(i, i + 1); if (x != -1000 && X[0] != x && X[1] != x && X[2] != x) X[cnt++] = x;// 邊界解會重複,去重 } printf("%.2lf %.2lf %.2lf", X[0], X[1], X[2]); return 0; }
END感謝reader's閱讀,洛谷題目連結:P1024 [NOIP2001 提高組] 一元三次方程求解 - 洛谷 | 電腦科學教育新生態 (luogu.com.cn)