一元三次方程 (codevs 1038)題解

2021-07-09 09:34:38 字數 1873 閱讀 3095

【問題描述】

1 -5 -4 20

-2.00 2.00 5.00

本題為noip2001 提高組第二題,可用兩種方法解決,列舉/二分,但老師改了一下資料,將保留2位改為了保留4位,導致列舉會超時,無奈之下用了二分……這裡還是講保留2位小數。題目中的提示已經完完全全告訴了我們思路,設f(x)=a*x^3+b*x^2+c*x+d,若用列舉,從-100開始,每次加0.01,按題目說明,如果f(x-0.005)*f(x+0.005)<0,那麼,x即是答案(題目要求保留兩位小數,只需write的時候加上:0:2即可,無需再判斷x),或者f(x)本身就等於0,x也是答案。詳見**。

下面為二分題解。

二分是由分治策略引申的一種解題方法,比列舉會更快一些,所謂二分,就是將題目從中間分為兩個部分,再對左右兩邊的分問題進行解答,將最終答案遞迴回來即可。

提示又給了我們很好的思路,這就是典型的二分了。如果f(x1)*f(x2)<0或者x1+1>x2,那麼就從中間分為兩個部分,為什麼是或者呢?題目中說根與根的差的絕對值》=1,因此,如果我們找的兩個數的差大於1,那麼有可能這兩個數中間不止存在乙個解,因此也需要二分,利用這個特性,我們可以之間將-100與100二分。終止條件:(f(x)=0)or((x1+0.001>x2)and(f(x1)*f(x2)<0)這裡的終止條件與列舉不同,但原理是一樣的同樣是因為需要保留兩位小數,因此需要判斷三位。詳見**。

var

a,b,c,d,x:real;

w:integer;

function

f(x1:real):real;

begin

f:=a*x1*x1*x1+b*x1*x1+c*x1+d;

end;

begin

x:=-100

; readln(a,b,c,d);

repeat

x:=x+0.01;

if (f(x)=0) or (f(x-0.005)*f(x+0.005)<0) then//注意這裡的條件,有兩種情況都算作根

begin

write(x:

0:2,'');

inc(w);

end;

until w=3

;end.

列舉法

1

vara,b,c,d:double;

2i:longint;

3function

js(x:double):double;

4begin

5 js:=a*x*x*x+b*x*x+c*x+d;

6end;7

procedure

try(x1,x2:double);

8var

x0,y0,y1,y2:double;

9begin

10 x0:=(x1+x2)/2

;11 y0:=js(x0);y1:=js(x1);y2:=js(x2);

12if (y0=0)or((x1+0.001>x2)and(y1*y2<0))then//滿足條件,輸出

13begin

14 write(x0:0:2,'');

15exit;

16end;17

if (y1*y0<0)or(x0-x1>1) then//注意題中說了兩個解之間的差的絕對值》=1,所以遞迴的條件不只是單純的f(x1)*f(x0)<0

18try(x1,x0);

19if (y0*y2<0)or(x2-x0>1) then

20try(x0,x2);

21end;22

begin

23readln(a,b,c,d);

24 try(-100,100

);25

end.

二分法

一元三次方程求解

有形如 ax 3 bx 2 cx d 0這樣的乙個一元三次方程。給出該方程中各項的係數 a,b,c,d均為實數 並約定該方程存在三個不同實根 根的範圍在 100至100之間 且根與根之差的絕對值 1。要求由小到大依次在同一行輸出這三個實根 根與根之間留有空格 並精確到小數點後2位。輸入有多行測試資料...

一元三次方程求解

問題描述 有形如 ax 3 bx 2 cx d 0 這樣的乙個一元三次方程。給出該方程中各項的係數 a,b,c,d 均為實數 並約定該方程存在三個不同實根 根的範圍在 100至100之間 且根與根之差的絕對值 1。要求三個實根。輸入格式 四個實數 a,b,c,d 輸出格式 由小到大依次在同一行輸出這...

一元三次方程求解

有形如 ax3 bx2 cx d 0 這樣的乙個一元三次方程。給出該方程中各項的係數 a,b,c,d 均為實數 並約定該方程存在三個不同實根 根的範圍在 100至100之間 且根與根之差的絕對值 1。要求由小到大依次在同一行輸出這三個實根 根與根之間留有空格 並精確到小數點後2位。輸入格式 一行,4...