洛谷题单指南-二分查找与二分答案-P1024 [NOIP2001 提高组] 一元三次方程求解
原题链接:https://www.luogu.com.cn/problem/P1024
题意解读:方程在-100~100范围内有三个根,则必然存在两个数l<r,使得f(-100) * f(l)<0,f(l)*f(r)<0,f(r)*f(100)<0
解题思路:
设方程的三个根是x1、x2、x3,l在x1、x2之间,r在x2、x3之间,如图

由于三个跟之间距离>=1,最小是1,所以l、r在枚举的时候递增要小于1,用0.5递增即可
找l的代码片段如下:
double i = -100;
while(i <= 100)
{
if(f(i) * f(-100) < 0)
{
l = i;
break;
}
i += 0.5;
}
找r的代码片段如下:
while(i <= 100)
{
if(f(i) * f(l) < 0 && f(i) * f(100) < 0)
{
r = i;
break;
}
i += 0.5;
}
然后进行三次实数二分操作,分别在-100~l,l~r,r~100区间内找一个根
二分的判定条件是:
对于左边界l,右边界r,中间值mid
如果f(l) * f(mid) <= 0,表示有根,继续减少r的范围,r=mid
否则表示没有根,提升l的范围,l=mid
100分代码:
#include <bits/stdc++.h>
using namespace std;
double a, b, c, d;
double l = -100, r = 100;
double f(double x)
{
return a * x * x * x + b * x * x + c * x + d;
}
double bs(double l, double r)
{
while(r - l > 1e-4)
{
double mid = (l + r) / 2;
if(f(l) * f(mid) <= 0) r = mid;
else l = mid;
}
return r;
}
int main()
{
cin >> a >> b >> c >> d;
double i = -100;
while(i <= 100)
{
if(f(i) * f(-100) < 0)
{
l = i;
break;
}
i += 0.5;
}
while(i <= 100)
{
if(f(i) * f(l) < 0 && f(i) * f(100) < 0)
{
r = i;
break;
}
i += 0.5;
}
double x1 = bs(-100, l);
double x2 = bs(l, r);
double x3 = bs(r, 100);
printf("%.2lf %.2lf %.2lf", x1, x2, x3);
return 0;
}
浙公网安备 33010602011771号