vijos p1116(codevs 1038 )一元三次方程求解 题解

来源:互联网 发布:老炮儿 网络剧 编辑:程序博客网 时间:2024/06/05 02:36

题目描述 Description

有形如:ax3+bx2+cx+d=0  这样的一个一元三次方程。给出该方程中各项的系数(abcd  均为实数),并约定该方程存在三个不同实根(根的范围在-100100之间),且根与根之差的绝对值>=1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后2位。
提示:记方程
f(x)=0,若存在2个数x1x2,且x1<x2f(x1)*f(x2)<0,则在(x1x2)之间一定有一个 根。

输入描述 Input Description

一个三次方程的各项系数

输出描述 Output Description

三个解

样例输入 Sample Input

1   -5   -4   20

样例输出 Sample Output

-2.00   2.00   5.00

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

这道题是一道明显的二分题。

有题可知精度为0.01,且三个解均在-100到100之间。由于范围小,精度确定,所以我们可以用二分的方法去求解。

网上有一些题解,这里我给出我的,和大家一起共享。

首先我们可以求导,必然的到两个极值点,而这两个极值点是由a,b,c,决定的,及求导后得到的一元二次方程的解。这两个极值便是我们划分区间的界限(f(x1),f(x2))我们便可以得到一个区间——(-100,f(x1))(f(x1),f(x2))(f(x2),100)

由函数图象的性质可知若一个区间的两端的函数值乘积小于0,则这个区间上必有解,这样我们就可以一直二分下去,知道区间的两端之差<=0.01时便可以退出了。

关于二分,有兴趣的读者,可以看一下我的下一篇文章——《二分哪些事儿》

……比较坑的是,我把a*x*x*x+b*x*x+c*x+d写成了a*x*x*x+b*x*x+c+d导致我一直输出错误,大家一定要注意!

++++++++++++++++++++++++代码如下+++++++++++++++++++++++++++++

首先是用二分的:

#include <cstdio>#include <cmath>using namespace std;double a,b,c,d;double fang(double x){ return a*x*x*x+b*x*x+c*x+d; }double Bi_Search(double left,double right)//返回等于b的第一个{double last = -1,mid ;while (left<=right){double mid = left +(right-left)/2;if(right-left<=0.01){last = mid;right = mid -1;}else if(fang(mid)*fang(right)<0) left = mid;             else right = mid;}return last;}int main(){    cin>>a>>b>>c>>d;    double aa=3*a,bb=2*b,x=100.00,y,m,n=-100.00;    y=(-bb+sqrt(bb*bb-4*aa*c))/(2*aa);    m=(-bb-sqrt(bb*bb-4*aa*c))/(2*aa); cout<<y<<" "<<m<<endl;    double x1=Bi_Search(n,m),x2=Bi_Search(m,y),x3=Bi_Search(y,x);    printf("%.2lf %.2lf %.2lf",x1,x2,x3);    return 0;}


这里还有一个用公式直接求解的:

#include <cstdio>#include <cmath>#include <algorithm>using namespace std;void mmax(double &x,double &y,double &z){double a[3];a[0]=x,a[1]=y,a[2]=z;sort(a,a+3);x=a[0],y=a[1],z=a[2];return ;}int main(){double A,B,C,a,b,c,d;cin>>a>>b>>c>>d;A=b*b-3*a*c;B=b*c-9*a*d;C=c*c-3*b*d;double t=2*A*b-3*a*B;t/=2*sqrt(A*A*A);double cr=acos(t);double x_1,x_2,x_3;x_1=(-b-2*sqrt(A)*cos(cr/3))/3*a;x_2=(-b+sqrt(A)*(cos(cr/3)+sqrt(3)*sin(cr/3)))/3*a;x_3=(-b+sqrt(A)*(cos(cr/3)-sqrt(3)*sin(cr/3)))/3*a;mmax(x_1,x_2,x_3);printf("%0.2lf %0.2lf %0.2lf",x_1,x_2,x_3);return 0;}


1 0