洛谷 P1024 一元三次方程求解 二分 枚舉

洛谷 P1024 一元三次方程求解 二分 枚舉

https://www.luogu.com.cn/problem/P1024

題目描述

有形如:ax3+bx2+cx1+dx0=0ax^3 + bx^2 + cx^1 + dx^0=0 這樣的一個一元三次方程。給出該方程中各項的係數(a,b,c,d均爲實數),並約定該方程存在三個不同實根(根的範圍在*-100100*之間),且根與根之差的絕對值≥1。要求由小到大依次在同一行輸出這三個實根(根與根之間留有空格),並精確到小數點後2位。

提示:記方程f(x)=0,若存在2個數x1x2,且x1<x2,f(x1)×f(x2)<0,則在(x1,x2)之間一定有一個根。

輸入格式

一行,4個實數A,B,C,D

輸出格式

一行,3個實根,並精確到小數點後2位。

輸入輸出樣例

輸入 #1

1 -5 -4 20

輸出 #1

-2.00 2.00 5.00

思路:

求出兩個導數零點,將函數分成三個區域,每個區域中存在一個實根

對每個區域進行二分查找

代碼:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const double PI = 3.141592;
const int e = 1e-3;

double a, b, c, d;

double cal(double x){
    return a * x * x * x + b * x * x + c * x + d;
}

double tiwce(double l, double r){
    double ans = l;
    while(r - l > 1e-3){   //控制精度
        double mid = (r + l) / 2;
        if(cal(l) * cal(mid) < 0) r = mid;
        else l = mid;
        ans = mid;
    }
    return ans;
}

int main()
{
    scanf("%lf %lf %lf %lf", &a, &b, &c, &d);
    double edg1, edg2;
    //求導數零點
    edg1 = (-2 * b + sqrt(4 * b * b - 12 * a * c)) / (6 * a);
    edg2 = (-2 * b - sqrt(4 * b * b - 12 * a * c)) / (6 * a);
    if(edg1 > edg2){
        double temp;
        temp = edg1;
        edg1 = edg2;
        edg2 = temp;
    }
    double ans[3];
    ans[0] = tiwce(-100, edg1);
    ans[1] = tiwce(edg1, edg2);
    ans[2] = tiwce(edg2, 100);
    sort(ans, ans + 3);
    printf("%.2f %.2f %.2f\n", ans[0], ans[1], ans[2]);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章