有形如:ax^3+bx^2+cx^1+dx^0=0ax3+bx2+cx1+dx0=0 這樣的一個一元三次方程。給出該方程中各項的係數(a,b,c,da,b,c,d均爲實數),並約定該方程存在三個不一樣實根(根的範圍在-100−100至100100之間),且根與根之差的絕對值\ge 1≥1。要求由小到大依次在同一行輸出這三個實根(根與根之間留有空格),並精確到小數點後22位。html
提示:記方程f(x)=0f(x)=0,若存在22個數x_1x1和x_2x2,且x_1<x_2x1<x2,f(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 -5 -4 20
-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
若是不會公式,能夠根據題意:(根的範圍在-100−100至100100之間),且根與根之差的絕對值\ge 1≥1,邊枚舉,邊二分。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; }