P1024 [NOIP2001 提高组] 一元三次方程求解 /1238:一元三次方程求解

# [NOIP2001 提高组] 一元三次方程求解

## 题目描述

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

提示:记方程 $f(x) = 0$,若存在 $2$ 个数 $x_1$ 和 $x_2$,且 $x_1 < x_2$,$f(x_1) \times f(x_2) < 0$,则在 $(x_1, x_2)$ 之间一定有一个根。

## 输入格式

一行,$4$ 个实数 $a, b, c, d$。

## 输出格式

一行,$3$ 个实根,从小到大输出,并精确到小数点后 $2$ 位。

## 样例 #1

### 样例输入 #1

```
1 -5 -4 20
```

### 样例输出 #1

```
-2.00 2.00 5.00
```

## 提示

**【题目来源】**

NOIP 2001 提高组第一题

1238:一元三次方程求解

时间限制: 1000 ms         内存限制: 65536 KB
提交数: 8791     通过数: 4561

【题目描述】

形如: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

【算法分析】

这是一道有趣的解方程题。为了便于求解,设方程f(x)=a+b+cx+d=0,设根的值域(-100至100之间)中有x,其左右两边相距0.0005的地方有n和m两个数,即n=x-0.0005,m=x+0.0005。n和m间的距离(0.001)满足精度要求(精确到小数点后2位)。

有两种方法计算f(x)=0的根x:

(1)枚举法

根据根的值域和根与根之间的间距要求(>=1),我们不妨将根的值域扩大100倍(-10000<=x<=10000),依次枚举该区间的每一个整数值x,并在题目要求的精度内设定区间:n=,m=。若区间端点的函数值f(n)和f(m)异号或者在区间端点n的函数值f(n)=0,则确定为f(x)=0的一个根。

由此得出算法:

#include<stdio.h>
#include<iostream>
using namespace std;
double a,b,c,d,n,m;
double f(double x)//计算a*x^3+b*x^2+c*x+d
{return a*x*x*x+b*x*x+c*x+d;
}//f函数
signed main()
{scanf("%lf%lf%lf%lf",&a,&b,&c,&d);for(double i=-10000;i<=10000;i++)//枚举当前根*100的可能范围{n=(i-0.05)/100,m=(i+0.05)/100;//在题目要求的精度内设定区间 if(f(n)*f(m)<0 or f(n)==0)printf("%.2lf ",i/100);//若在区间两端的函数值异号或在n处的函数值为0,则确定i/100为根}return 0;
}

给个关注吧

给个关注吧

(2)分治法

枚举根的值域中的每一个整数x(-100<=x<=100)。由于根与根之差的绝对值>=1,因此设定搜索区间[l,r],其中l=x,r=x+1。

(1)若f(l)=0,则确定l为f(l)的根;

(2)若f(l)*f(r)>0,则确定根x不在区间[l,r]内,设定[r,r+1]为下一个搜索区间;

(3)若f(l)*f(r)<0,则确定根x在区间[l,r]内。

如果确定根在区间[l,r]内的话(f(l)*f(r)<0),如何在该区间找到根的确切位置。采用二分法,将区间[l,r]分成左右两个子区间:左子区间[l,x]和右子区间[x,r](其中x=):

若f(l)*f(x)<=0,则确定根在左子区间[l,x]内,将x设为该区间的右指针(r=x),继续对左子区间进行对分;若f(l)*f(x)>0,则确定根在右子区间[x,r]内,将x设为该区间的左指针(l=x),继续对右子区间进行对分;

上述对分过程一直进行到区间的间距满足精度要求为止(r-l<0.001)。此时确定l为f(x)的根。

由此得出算法:

#include<stdio.h>
#include<iostream>
using namespace std;
double a,b,c,d,l,r,mid;
double f(double x)//将x代入函数
{return a*x*x*x+b*x*x+c*x+d;
}
signed main()
{scanf("%lf%lf%lf%lf",&a,&b,&c,&d);for(double i=-100;i<=100;i++)//枚举每一个可能的根{l=i,r=i+1;//确定根的可能区间if(f(l)==0)printf("%.2lf ",l);//若l为根,则输出else if(f(l)*f(r)<0)//若根在区间[l,r]中{while(r-l>=0.001)//若区间[l,r]不满足精度要求,则循环{mid=(l+r)/2;//计算区间[l,r]的中间位置if(f(l)*f(mid)<1)r=mid;//若根在左子区间,则调整右指针else l=mid;//若根在右子区间,则调整左指针}printf("%.2lf ",l);//区间[l,r]满足精度要求,确定l为根}}return 0;
}

给个关注吧

P1024 [NOIP2001 提高组] 一元三次方程求解 /1238:一元三次方程求解相关推荐

  1. 洛谷——P1024 [NOIP2001 提高组] 一元三次方程求解

    P1024 [NOIP2001 提高组] 一元三次方程求解 题目描述 有形如:a x^3 + b x^2 + c x + d = 0a**x3+b**x2+c**x+d=0 这样的一个一元三次方程.给 ...

  2. 题目:P1024 [NOIP2001 提高组] 一元三次方程求解

    题目:[NOIP2001 提高组] 一元三次方程求解 - 洛谷 题目大意 给定4个数作为一元三次方程的系数,再用2位小数计算出3个根 数据类型 double 思路 输入进行条件判断 代码 #inclu ...

  3. P1024 [NOIP2001 提高组] 一元三次方程求解

    题目描述 有形如:a x^3 + b x^2 + c x + d = 0ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,da,b,c,d 均为实数),并约定该 ...

  4. 洛谷P1024 [NOIP2001 提高组] 一元三次方程求解 C++ 思路加代码

    这道题吧,它分两个解法,一个是规规矩矩用算法,另一个是暴力枚举.因为俗话说的好,"算法不争气,暴力出奇迹",没学过二分的就抄歪解吧. 1.暴力算法     简单粗暴,一个循环,遍历 ...

  5. P1027 [NOIP2001 提高组] Car 的旅行路线 (图 最短路)

    原题链接:[NOIP2001 提高组] Car 的旅行路线 - 洛谷 AC代码: #include<bits/stdc++.h> using namespace std; #define ...

  6. [NOIP2001] 提高组 洛谷P1024 一元三次方程求解

    题目描述 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差 ...

  7. c++一元三次方程求解(NOIP2001 提高组)

    先看题: 有形如:ax3+bx2+cx+d=0a x^3 + b x^2 + c x + d = 0ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,da,b, ...

  8. [NOIP2001 提高组] 一元三次方程求解

    题目描述 有形如:ax3+bx2+cx+d=0a x^3 + b x^2 + c x + d = 0ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,da,b, ...

  9. P5017 [NOIP2018 普及组] 摆渡车(pj组最后一道蓝) P1027 [NOIP2001 提高组] Car 的旅行路线(提高组第一道蓝)

    先从简单的说 确实 我是看着AC率高的才选的 没有辜负我的期望 他真的很简单 数据范围很小 一眼floyd 然后就秒了 注意得就是我们还是把每个点编号再跑最短路 然后我们可以把相邻的四个放一起处理 还 ...

最新文章

  1. C#拾遗(一、基本类型)
  2. 我的2017与2018
  3. pandas如何保存在excel里面_【精选】Pandas一站式教程!
  4. linux内核5.3支持cpu,Linux 5.3版内核重磅发布:支持中国兆芯x86 CPU
  5. 博客开源系统(待续......)
  6. LeetCode Algorithm 101. Symmetric Tree
  7. java怎么使用wcf_如何使用WCF服务
  8. iBatis的基本配置+CRUD操作
  9. 火狐浏览器手机版_hao123导航app下载-hao123浏览器手机版下载
  10. c++ stl string char* 向 string 转换的问题
  11. python基础:集合操作
  12. python字符串格式化符号含义及转义字符含义
  13. 聊聊强AI——来到治愈系空间的小茶末
  14. 网络安全技术第八章——虚拟专用网络
  15. 狼行千里吃肉,马行千里吃草(我读了5遍,震撼了!)
  16. 红旗linux考试,红旗Linux认证考试介绍
  17. Linux监控软件之 Nagios
  18. 云POS连锁版收银系统免费试用 超市连锁收银软件免费注册
  19. jmeter高分辨率适配 + 参数栏正常显示
  20. 降压电荷泵原理详细介绍

热门文章

  1. Struts2中XXX.Action类中方法的访问(三种方式)
  2. win10自带sftp服务器_FreeSSHD在Windows环境下搭建SFTP服务器
  3. nao机器人学习笔记3
  4. mysql增加时间戳
  5. 论文大致思路(不断更新)
  6. xss漏洞学习心得(泪目)
  7. 薅羊毛的机会了,点个“赚”即有机会赚取高额佣金
  8. 随笔记录——numpy4(伪随机数生成)
  9. 微信报错errcode大全
  10. 最基础且详细的 RPCA-ALM 算法推导过程(手写稿)