【問題描述】
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...