1. 题目
一元三次方程求解
有形如:ax^3+bx^2+cx+d=0 这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-10000至10000之间),且根与根之差的绝对值>=1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后4位。
输入格式
4个实数,分别表示三次项系数,二次项系数,一次项系数,常数项(每个的系数均保证绝对值在10^9以内)
输出格式
一行三个实数,为方程的3个实根,精确到小数点后4位
输入样例
1 0 -1 0
输出样例
-1.0000 0.0000 1.0000
2. 题目实质
NOIP 2001 提高组 第一题 。。。。。。的改版。
3. 算法
枚举每一个长度为 1 的区间,然后,当发现区间的两个端点代到方程中后,恰好一个为正值,一个为负值,这就说明这个区间中有一个根。(不知道为什么的回去问数学老师去)
然后,对这个区间进行二分,原理还是当两个端点代到方程中后,恰好一个为正值,一个为负值,这就说明这个范围内有一个根。
二分到出现精确根,或是精度够了为止。
4. 注意事项
原版可以用枚举,但改版只能用二分。
注意这一句“根与根之差的绝对值>=1”,别想太复杂了,直接二分长度为 1 的区间就行了。
5. 代码
二分 (ZSZ)
Program Test(input,output);
var a,b,c,d,q,p:real;
ans:array[1..3]of real;
i,t:longint;
Function F(x:real):real;
begin F:=((a*x+b)*x+c)*x+d;end;
Function findx(i:real):real;
begin
p:=i;q:=p+0.999999;
if(abs(F(p))<0.00001)then findx:=p
else begin
while(p+0.00001<q)and(F((p+q)/2)<>0)do
if(F(p)*F((p+q)/2)<0)then q:=(p+q)/2
else p:=(p+q)/2;
exit((p+q)/2);
end;
end;
begin
assign(input,'equation.in');reset(input);
assign(output,'equation.out');rewrite(output);
readln(a,b,c,d);t:=0;
for i:=-10000 to 10000 do
begin
if(abs(F(i))<0.000001)or(F(i)*F(i+0.999999)<=0)then
begin inc(t);ans[t]:=findx(i);end;
if t=3 then break;
end;
for t:=1 to 3 do
write(ans[t]:0:4,' ');
close(input);
close(output);
end.