P1024 一元三次方程求解

題目描述

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

提示:記方程f(x)=0f(x)=0,若存在22個數x_1x1x_2x2,且x_1<x_2x1<x2f(x_1) \times f(x_2)<0f(x1)×f(x2)<0,則在(x_1,x_2)(x1,x2)之間必定有一個根。ios

輸入輸出格式

輸入格式:spa

 

一行,44個實數A,B,C,DA,B,C,D。code

 

輸出格式:htm

 

一行,33個實根,並精確到小數點後22位。blog

 

輸入輸出樣例

輸入樣例#1:  複製
1 -5 -4 20
輸出樣例#1:  複製
-2.00 2.00 5.00

解析1:暴力枚舉(暴力出奇跡)
由於解的取值範圍(-100~100),結果保留小數點後2位,徹底能夠枚舉解決。須要注意的是,只有知足如下條件,才能肯定解:
 double l=i,r=i+0.001; if((a*l*l*l+b*l*l+c*l+d)*(a*r*r*r+b*r*r+c*r+d)<0){ printf("%.2lf ",l);
而不能直接
a*l*l*l+b*l*l+c*l+d=0,實數由於精度問題,結果未必能直接等於0
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
    double a,b,c,d;
    int num=0;
    cin>>a>>b>>c>>d;
    for(double i=-100.00;i<=100.00;i+=0.001){
        double l=i,r=i+0.001;
        if((a*l*l*l+b*l*l+c*l+d)*(a*r*r*r+b*r*r+c*r+d)<0){// 若存在兩個數x1,x2且x1<x2,f(x1)*f(x2)<0 則方程解確定在x1~x2範圍內  
            printf("%.2lf ",l);
            num++;// 小數點後兩位輸出
            if (num>=3)break;//找到3個解直接退出循環,提升時間複雜度。 
        }
    }
    return 0;    
}

 

解析2:二分ci

若是不會公式,能夠根據題意:(根的範圍在-100100至100100之間),且根與根之差的絕對值\ge 11,邊枚舉,邊二分。it

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=50050;
    double a,b,c,d;
double f(double x){
    return a*x*x*x+b*x*x+c*x+d ;    
}
int main(){
    cin>>a>>b>>c>>d;
    for(int i=-100;i<100;i++)
        if (f(i)*f(i+1)<0){
            double l=i,r=i+1,eps=1e-4,mid;
            for(int j=1;j<=100;j++){
                mid=(l+r)/2;
                if(f(l)*f(mid)<=0) {
                  r=mid;
                }
                else l=mid;
            }
            printf("%.2lf ",mid);
        }
        else if(f(i)==0) printf("%.2lf ",double(i));
    return 0;
}
相關文章
相關標籤/搜索