信息学奥赛一本通(1238:一元三次方程求解)
1238:一元三次方程求解
時間限制: 1000 ms ??? ??? 內存限制: 65536 KB
提交數: 6364 ??? 通過數: 3241
【題目描述】
形如:ax^3+bx^2+cx+d=0 這樣的一個一元三次方程。
給出該方程中各項的系數(a,b,c,d 均為實數),并約定該方程存在三個不同實根(根的范圍在?100至100之間),且根與根之差的絕對值≥1。要求由小到大依次在同一行輸出這三個實根(根與根之間留有空格),并精確到小數點后2位。
【輸入】
一行,包含四個實數a,b,c,d,相鄰兩個數之間用單個空格隔開。
【輸出】
一行,包含三個實數,為該方程的三個實根,按從小到大順序排列,相鄰兩個數之間用單個空格隔開,精確到小數點后2位。
【輸入樣例】
1.0 -5.0 -4.0 20.0【輸出樣例】
-2.00 2.00 5.00【分析】
? ? ? ? 數學中,一個十分基本的問題是求給定方程的解。如下列方程:
? ? ? ? 4X^5 - 3X^4 + 2X^3 + 6X^2 + 5X - 7 = 0
? ? ? ? x+ sinx - 3=0
? ? ? ? x^10 -10x = 0
? ? ? ? lgx - x^2 + 7x + 5 = 0
? ? ? ? 它們的一般形式可表示為:f(x)=0。方程的根或解是使f(x)等于0的那些x的值。這里,我們僅考慮x為實數的情況。方程f(x)=0可能無根,有單根、多根,甚至有無窮多根。求解這個問題,可以采用枚舉法,也可以采用分治法。
? ? ? ? 方法1:枚舉法。分析一下,根的范圍在-100到100之間,以根為枚舉對象,枚舉范圍是-100到100,因為結果要保留兩位小數,故此,步長為0.001。 將枚舉的根,代入原方程,利用誤差法,對原方程式進行一一驗證,找出方程的解。
【參考代碼1】
#include <stdio.h> #include <math.h> double a,b,c,d; double f(double x) {return ((a*x+b)*x+c)*x+d; } int main() {double i;scanf("%lf%lf%lf%lf",&a,&b,&c,&d);for(i=-100;i<=100;i+=0.001)if(fabs(f(i))<1e-6)printf("%.2lf ",i);printf("\n");return 0; }? ? ? ? 方法2:分治法。二分法要求將方程改寫成f(x)=0的形式,然后y=f(x)。先選取x1和x2兩點,使f(x1)和f(x2)異號。由于y=f(x)是連續不斷的曲線,故在x1和x2之間至少有一個根存在。先將可變區間[x1,x2]兩等分,求出其中點,即x3=(x1+x2)/2,然后求出函數在中點處的值f(x3)。若f(x3)與f(x1)同號,則新的可變區間就是[x3,x2];如果異號,則新的可變區間是[x1,x3];如果f(x3)=0,則求解完畢。如此重復疊代下去,直至可變區間之長度小于某個預先給定的值為止,或者達到f(x) = 0。?
【參考代碼2】
#include<stdio.h> #include<math.h> double a,b,c,d; double F(double x) {return ((a*x+b)*x+c)*x+d; } int main() {int i;double x1,x2,xb;scanf("%lf%lf%lf%lf",&a,&b,&c,&d);for(i=-100;i<=100;i++){x1=i;x2=i+0.99999; //注意此處不能用 x2=i+1,否則 else if 分支求一個,if分支又求一個,重復了if(fabs(F(x1))<1e-6)printf("%.2lf ",x1);else if(F(x1)*F(x2)<0){xb=(x1+x2)/2;while(fabs(x2-x1)>1e-6) // x1 != x2, 二分法找到根 {if(F(x1)*F(xb)>0)x1=xb;elsex2=xb;xb=(x1+x2)/2; }printf("%.2lf ",xb); }}printf("\n");return 0; }http://ybt.ssoier.cn:8088/problem_show.php?pid=1238
總結
以上是生活随笔為你收集整理的信息学奥赛一本通(1238:一元三次方程求解)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信息学奥赛一本通 2053:【例3.3】
- 下一篇: 信息奥赛一本通(1325:【例7.4】