1814: 一元三次方程求解
时间限制: 1 Sec 内存限制: 128 MB
提交: 22 解决: 15
[提交][状态][讨论版]
题目描述
有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差的绝对值> =1。要求三个实根。。
输入
四个实数:a,b,c,d。数据规模和约定 |a|,|b|,|c|,|d|< =10
输出
由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后2位
样例输入
1 -5 -4 20
样例输出
-2.00 2.00 5.00
提示
来源
【解析】
哎呀,其实这个就是,那个什么,就是那个,对,很简单的莫。
看一题目说存在三个不同的根,嗯!范围还是-100--100,嗯!根与根之间的差>=1,(PS:其实一开始我不知道这个条件有什么用,WA了一次我知道干嘛用了。。。。)
一般这种数据规模这么小的,没有好的想法只能枚举了呗,但是这个枚举需要一点小tips,就是先扩大100倍(因为要精确到两位小数)然后再算,当然不用也可以,for里面的步长改为0.01应该也行。
#include <bits/stdc++.h>
using namespace std;
double a, b, c, d;
double f(double x)
{
return a * x*x*x + b * 1.0 * x*x + c * 1.0 * x + d;//这个没什么好说的
}
int main()
{
double temp1,temp2;
while (~scanf("%lf%lf%lf%lf", &a, &b, &c, &d))
{
int flag = 1; //用来控制输出格式
for (double i = -10000; i <= 10000; i++)//扩大100倍
{
temp1 = (i - 0.5)/ 100.0; //这里就是我一开始不懂为什么要说两根只差绝对值小于等于1的地方了
temp2 = (i + 0.5)/ 100.0; //因为……什么呢,四舍五入啊。。。。。。
if (f(temp1)*f(temp2)<0)
{
if (flag) //第一次输出不带空格,以后都带
{
printf("%.2lf", i / 100.0);
flag = 0;
continue;
}
else printf(" %.2lf", i / 100.0);
}
}
puts(""); //格式控制一下,也没什么好说的,(那我为什么要说这么多)
//我就是未来程序员特别的那个,特别喜欢写注释,YEAH~
}
return 0;
}
这个其实太麻瓜了。百度了一下一元三次方程其实是有通解方法的。
/*以下与A题目无关,赶时间的上面看完可以走了*/
这要用到高数的知识,一元三次方程的导数f'(x)=3ax^2+2bx+c。然后解个方程3ax^2+2bx+c=0,求得的两个根x1,x2就是极值点,那么f(x)=0的3个根就应该在区间[-100,x1]、[x1,x2]、[x2,100]中。无视开闭,关系不大。
然后再用二分法,很快就找到三个解了。
找来的代码,看看就好。
#include <stdio.h>
#include <math.h>
#define MIN_ERR 1e-4
double a, b, c, d;
double f(double x)
{
return a * x*x*x + b * x*x + c * x + d;
}
double find_sol(double min, double max)
{
if (max - min<MIN_ERR) return (min + max) / 2;
else
{
double f1, f2, f3;
f1 = f(min);
f2 = f((min + max) / 2);
f3 = f(max);
if (f2 == 0) return (min + max) / 2;
else if (f1*f2<0) return find_sol(min, (min + max) / 2);
else return find_sol((min + max) / 2, max);
}
}
int main()
{
double x1, x2;
scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
if (a<0)
{
a = -a;
b = -b;
c = -c;
d = -d;
}
x1 = (-2 * b - sqrt(4 * b*b - 12 * a*c)) / (a * 6);
x2 = (-2 * b + sqrt(4 * b*b - 12 * a*c)) / (a * 6);
printf("%.2lf %.2lf %.2lf\n", find_sol(-101, x1), find_sol(x1, x2), find_sol(x2, 101));
return 0;
}