今天分享的是P1024 [NOIP 2001 提高组] 一元三次方程求解,想要AC的话,他并不是一道难题。因为一精度要求低,二范围小。即使是用暴力的方法也能做出来。我采用的是暴力的方法,贴一下代码。
#include <bits/stdc++.h>
using namespace std;
int main(){
double a,b,c,d;
cin>>a>>b>>c>>d;
cout<<fixed<<setprecision(2);
for(double i=-100;i<=100;i+=0.001){
double j=i+0.001;
double y1=a*i*i*i+b*i*i+c*i+d;
double y2=a*j*j*j+b*j*j+c*j+d;
if(y1>=0&&y2<=0||y1<=0&&y2>=0){
double x=(i+j)/2;
cout<<x<<" ";
}
}
return 0;
}
但是其中有个控制小数位数的函数可以记一下,就是cout<<fixed<<setprecision(n)。按此格式输入便可以把之后全局的小数精度都改成小数后几位。
但是本题是归在二分法中的,当然就不能纯用暴力。这里参考了一下别人给出的题解。
#include<cstdio>
double a,b,c,d;
double fc(double x)
{
return a*x*x*x+b*x*x+c*x+d;
}
int main()
{
double l,r,m,x1,x2;
int s=0,i;
scanf("%lf%lf%lf%lf",&a,&b,&c,&d); //输入
for (i=-100;i<100;i++)
{
l=i;
r=i+1;
x1=fc(l);
x2=fc(r);
if(!x1)
{
printf("%.2lf ",l);
s++;
} //判断左端点,是零点直接输出。
//不能判断右端点,会重复。
if(x1*x2<0) //区间内有根。
{
while(r-l>=0.001) //二分控制精度。
{
m=(l+r)/2; //middle
if(fc(m)*fc(r)<=0)
l=m;
else
r=m; //计算中点处函数值缩小区间。
}
printf("%.2lf ",r);
//输出右端点。
s++;
}
if (s==3)
break;
//找到三个就退出大概会省一点时间
}
return 0;
}
核心是在中间的while循环,通过不断的缩小左端点和右端点对于根的距离,来把端点值逼近到符合精度的值,就可以得到结果。那么除此之外,还有公式法,一个是盛金公式,一个是卡尔丹公式。公式法就不贴代码了,这属于是需要记忆的,博主自己就记不住。当然迭代法也可以使用牛顿迭代法,或者割线法。