必威体育Betway必威体育官网
当前位置:首页 > IT技术

c++实现一元三次方程

时间:2019-07-29 18:10:00来源:IT技术作者:seo实验室小编阅读:90次「手机版」
 

一元三次方程

题目描述

有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程

给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差的绝对值>=1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后2位。

输入样例

1.0 -5.0 -4.0 20.0

输出样例

-2.00 2.00 5.00

##题目分析##

乍一看是一道数学题,没错确实可以用这种方法来做,但是当你遇到类似的题目,而又不知道公式的时候,就必须找另一种方法来解决,那我们就通过三种方法来讲述一下这道题目。

1:数学方法

2:模拟方法

3:分治方法

##数学方法##

这种方法就是直接套公式喽

这里写图片描述

如上图就是一元三次方程的公式

只需了解,背诵啥的等到高中吧(百度搜索:盛金公式)

#include <iOStream>
#include <math.h>
#include <iomanip>
using namespace std;
int main()
{
     double a,b,c,d;
     double as,bs,t,si;
     double x1,x2,x3;
     cin>>a>>b>>c>>d;
     as=b*b-3*a*c;
     bs=b*c-9*a*d;
     t=(2*as*b-3*a*bs)/(2*sqrt(as*as*as));
     si=acos(t);
     x1=(-b-2*sqrt(as)*cos(si/3))/(3*a);
     x2=(-b+sqrt(as)*(cos(si/3)+sqrt(3)*sin(si/3)))/(3*a);
     x3=(-b+sqrt(as)*(cos(si/3)-sqrt(3)*sin(si/3)))/(3*a);
     cout<<fixed<<setprecision(2)<<x1<<" ";
     cout<<fixed<<setprecision(2)<<x3<<" ";
     cout<<fixed<<setprecision(2)<<x2<<" ";
     return 0;
}

代码就差不多长这样,没啥好说的

##模拟方法##

直接暴力枚举也是一种方法,只可惜可能没发过所有的数据

枚举的思路就是在-100到100的范围内,以0.01为基准(在洛谷提交的经验)一个一个从小到大搜,搜到了就输出,这种思路还是十分水的,然而令我不能接受的是,这种漏洞百出的思路似乎还可以ac,谁叫洛谷数据只用搜索200*100=20000次呢,这种大家可以用五分钟来写一下,真的很简单啊。

下面是代码

#include<bits/stdc++.h>
using namespace std;
double a,b,c,d;
int main()
{
    cin>>a>>b>>c>>d;
    for(double i=-100.00;i<=100.00;i+=0.01)
    {
        if(a*i*i*i+b*i*i+c*i+d<0.00000001&&a*i*i*i+b*i*i+c*i+d>-0.00000001)
            printf("%.2f ",i);
    }
    return 0;
}

看上去很简单(实际上也很简单),可是还有一处细节,因为我们c++的double是定义到12位数的,所以在执行aiii+bii+ci+d时,它也会自动算到很后面很后面的位置,达不到完全相等,所以我不写0,反而是写>0.00000000001类似的,这样的话就避免了程序本身误差出现的问题,大家可以试一下,写0的d得0分,写>0.00000001满分,这简直跟大头的尺寸一样令人惊讶。

##分治算法##

好了终于到正常的方法了,这是一道敲经典的分治问题。

那问题来了,分治怎么分,以什么作为端点来分治?首先采用的便是二分策略,左端点x到中间点mid,中间点mid再到右端点y,以此类推。

但是这样的分治方法似乎效率没法提高,题目中有一句话:记方程f(x)=0,若存在两个数x1,x2且x1x2,f(x)*f(x2)<0,则在x,x2这个范围之中一定有一个解,我们可能不能了解这句话什么意思,但是我们可以照着这句话来写。先贴一下代码,然后我们慢慢探讨。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iomanip>
using namespace std;
double a,b,c,d; 
int now=0;  
double f(double x)      
{
    double res=a*x*x*x+b*x*x+c*x+d;
    return res;
}
void ser(double x,double y)  
{
    if(y-x<0.005)           
    {
        cout<<setprecision(2)<<x<<" ";
        now++;
        return ;
    }
    double mid = (x + y) / 2;          
    if(f(mid)==0)             
    {
     	cout<<setprecision(2)<<mid<<" ";     
     	now++;
     	return ;
    }
    if(f(x)*f(mid)<0) 
	{        
      	ser(x,mid);
	}
	if(f(mid)*f(y)<0)
	{
      	ser(mid,y);
	}
}
void work_()
{
    for(double i=-100;i<100;i++)
    {
        if(f(i)==0)
        {
            printf("%0.2lf",i);
            now++;
        }
        if(f(i)*f(i+1)<0)
		{       
          	ser(i,i+1);
    	}
		if(now==3) 
		{
			break;
		}
    }
}
int main()
{
    cin>>a>>b>>c>>d; 
    work_();
    return 0;
}

好,这里大致的思路已经ojbk了,那有几个细节,第一个地方就是变量now,now指的是当前有多少个解,一元三次方程只能有3个解,所以我们的now==3时,就停止运算,消减了很多的运算步骤。

还有就是当f(x)==0时,我们也是选择直接输出,多判断了一步,却可能省下很多步,十分的划算。

那好了,一元三次方程就讲完了

然后这道题方法很多,我再举出几种

比如数学超前学习的可以使用倒数来做,还有就是盛金公式的变化牛顿迭代法,有兴趣可以参考

相关阅读

淘宝一元拍卖设置提醒方法,商家如何参与该活动?

一元抢拍是对一些中小卖家进行扶持活动,是不分太多等级制度的,可以根据自己店铺需要,进行报销参加,加大产品展现量。接下来小编为大家

拼多多秒杀靠谱吗?怎样看待一元购和秒杀?

拼多多商城推出了很多优惠活动,而且都是极其便宜的,比如9.9特卖,0.1元购还有秒杀活动,这些都是优惠促销活动,拼多多经常用这些活动来吸

飞猪一元机票怎么抢?成功率高吗?

很多人都会使用飞猪这个订票软件,因为确实还是有一定的知名度,也让人放心购买,但是在这个上面真的能够购买到一折机票吗?如果能够购

一篇文章说透当下大热的一元夺宝!

2016,后泡沫互联网时代,资本更加谨慎。因此最火的两个项目,就成了变现模式清晰的“直播”和“一元夺宝”分析直播的文章已经汗牛充栋

微信夺宝在哪打开?微信公众号一元怎么夺宝?

说起微信夺宝的内容,我想大家肯定会存在一些疑惑。那么今天小编要给大家讲述的内容是微信夺宝在哪打开?微信公众号一元怎么夺宝?希

分享到:

栏目导航

推荐阅读

热门阅读