P1024 [NOIP2001 提高组] 一元三次方程求解
题目描述
有形如:a x^3 + b x^2 + c x + d = 0 这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d均为实数),并约定该方程存在三个不同实根(根的范围在 -100至 100之间),且根与根之差的绝对值 ≥1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后 2位。
提示:记方程 f(x) = 0,若存在 2 个数 x1 和 x2,且 x1<x2,f(x1)×f(x2)<0,则在 (x1,x2) 之间一定有一个根。
输入格式
一行,4 个实数 a,b,c,d。
输出格式
一行,3 个实根,从小到大输出,并精确到小数点后 2 位。
输入输出样例
输入
1 -5 -4 20
输出
-2.00 2.00 5.00
分析
二分或牛顿迭代之
代码
#include <bits/stdc++.h> #define Enter puts("") #define Space putchar(' ') using namespace std; typedef long long ll; typedef unsigned long long Ull; typedef double Db; inline ll Read() { ll Ans = 0; char Ch = ' ' , Las; while(!isdigit(Ch)) { Las = Ch; Ch = getchar(); } while(isdigit(Ch)) { Ans = (Ans << 3) + (Ans << 1) + Ch - '0'; Ch = getchar(); } if(Las == '-') Ans = -Ans; return Ans; } inline void Write(ll x) { if(x < 0) { x = -x; putchar('-'); } if(x >= 10) Write(x / 10); putchar(x % 10 + '0'); } inline ll Quick_Power(ll a , ll b) { ll Ans = 1 , Base = a; while(b != 0) { if(b & 1 != 0) Ans *= Base; Base *= Base; b >>= 1; } return Ans; } Db x1 , x2 , x3 , a , b , c , d; inline Db f(Db x) { return a * x * x * x + b * x * x + c * x + d; } inline Db df(Db x) { return 3 * a * x * x + 2 * b * x + c; } inline Db slove(Db l,Db r) { Db x , x0 = (l + r) / 2; while(abs(x0 - x) > 0.0001) x = x0 - f(x0) / df(x0) , swap(x0 , x); return x; } int main() { cin >> a >> b >> c >> d; Db p = (-b - sqrt(b * b - 3 * a * c)) / (3 * a); Db q = (-b + sqrt(b * b - 3 * a * c)) / (3 * a); x1 = slove(-100 , p); x2 = slove(p , q); x3 = slove(q , 100); printf("%.2lf %.2lf %.2lf" , x1 , x2 , x3); return 0; }