zoukankan      html  css  js  c++  java
  • 1238:一元三次方程求解

    【原始题目】

    1238:一元三次方程求解
    
    时间限制: 1000 ms         内存限制: 65536 KB
    提交数: 4113     通过数: 2017 
    【题目描述】
    形如:ax3+bx2+cx+d=0ax3+bx2+cx+d=0 这样的一个一元三次方程。
    
    给出该方程中各项的系数(a,b,c,da,b,c,d均为实数),并约定该方程存在三个不同实根(根的范围在−100−100至100100之间),且根与根之差的绝对值≥11。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后22位。
    
    【输入】
    一行,包含四个实数a,b,c,da,b,c,d,相邻两个数之间用单个空格隔开。
    
    【输出】
    一行,包含三个实数,为该方程的三个实根,按从小到大顺序排列,相邻两个数之间用单个空格隔开,精确到小数点后22位。
    
    【输入样例】
    1.0 -5.0 -4.0 20.0
    【输出样例】
    -2.00 2.00 5.00
    1238:一元三次方程求解

    【分析】

       依次搜索根的范围,找出三个根就OK。原理(连续函数零点存在定理):对于继续函数y=f(x),若f(a)*f(b)<0,则函数在区间(a,b)上必存在零点,那我们的任务就是找到两端点值异号的区间。由于两根差的经验值大于等于1,所以,我们逐个扫描整点函数值的符号就必有线索。(为了防止漏网之鱼,我把扫描间隔改为0.5)。找到范围再定位根,那就简单了——二分法。若f(a)*f(b)<0,取m=(a+b)/2,求f(m)的值。三种情况:1、运气比较好,f(m)=0,那就不用继续了,直接得结果。2、f(m)*f(a)>0,则f(m)*f(b)<0,把根的范围缩小到(m,b),继续递归,在(m,b)中找根。3、f(a)*f(m)<0,说明(a,m)内有根,同2,递归在(a,m)找根。

    注意:由于精度原因,符号的判定一般用把x>0改为x>1e-12,x<0改为x<-1e-12(也可以写-x>1e-12),其他情况视为x=0。这个问题在1058题中有说明。

    AC代码:

    //1238:一元三次方程求解
    #include<iostream>
    #include<iomanip> 
    using namespace std;
    int k;
    double ans[3],a,b,c,d,x0=-101;
    //x0是根所在区间的左界,根有可能是-100,所以x0必须小于-100 
    int f(double x)
    {
        double y;
        y=a*x+b;
        y=x*y+c;
        y=x*y+d;//写的有点复杂,顺便搞下秦九韶算法 
        if(-y>1e-12)return -1;
        else if(y>1e-12)return 1;
        else return 0;
    }
    
    //二分法找根,原理:连续函数y=f(x):f(a)*f(b)<0 ,则在(a,b)上必有一根 
    double key(double x,double y)
    {
        double m=(x+y)/2;
        if(y-x<0.0005||f(m)==0)return m;//精确到小数点后2位,最少多算一位,再送一次精度更高哈 
        if(f(x)*f(m)==1)return key(m,y);
        else return key(x,m);
    }
    int main(){
        cin>>a>>b>>c>>d;     
        for(double i=-100;i<=100;i+=0.5)
            if(f(i)==0)
            {
                ans[k++]=i;
                x0=i+0.5;//很重要,否则下次判断符号就错了 
                if(k==3)break;
            }
            else if(f(x0)*f(i)==1)x0=i;
            else 
            {
                ans[k++]=key(x0,i);
                x0=i;//很重要,否则下次判断符号就错了 
                if(k==3)break;
            }
        for(int i=0;i<3;i++)
        cout<<fixed<<setprecision(2)<<ans[i]<<' ';
        return 0;
    }
  • 相关阅读:
    【JBPM4】创建流程实例
    【JBPM4】流程部署
    Table上下滚动
    oracle 导入dmp文件
    Win7下安装Oracle 10g
    【Hibernate3.3复习知识点二】
    通过IP地址和子网掩码计算主机数
    vue.js知识总结
    vue生产环境部署总结
    移动端上遇到的各种坑与相对解决方案
  • 原文地址:https://www.cnblogs.com/wendcn/p/12576231.html
Copyright © 2011-2022 走看看