luogu1024 一元三次方程求解
Posted headboy2002
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu1024 一元三次方程求解相关的知识,希望对你有一定的参考价值。
题目大意
已知一元三次方程\(ax^3+bx^2+cx+d=0\):
- 有且只有3个根
- 对\(\forall x, x\in[-100,100]\)
- 对\(\forall x_1,x_2,|x_1-x_2|\geq1\)
- 定理:令\(f(x)=ax^3+bx^2+cx+d\),则\(f(l)f(r)<0\Leftrightarrow \exists x\in [l,r],使得f(x)=0\)
思路
本题中的条件3的表达形式太讨厌了,我们求点利用的是区间,想要的是区间的性质,这才有助于我们求点。怎么翻译3呢?性质3中的那个“1”指的是区间的长度。所以翻译为:对\(\forall p\),方程的根落在区间\([p,p+1]\)的个数不多于1。若个数等于1,则\(p,p+1\)性质4中的\(l,r\)的性质。
从拿到题开始我们很容易想到二分。二分求点,我们要的是点右方区间具有某一特定性质,点左方区间具有另一特定性质。这个“特殊性质”便是:一方有解,另一方无解。因此我们对于每个满足性质4的长度为1的区间二分即可。
注意
- 上文中的“特殊性质”不可以是“左侧图象在x轴一侧,右侧图像在x轴另一侧”,因为该区间上的图象不一定具有单调性,所以我们无法判断左右侧图象分别具体在x轴的上侧还是下侧。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const double EPS = 0.0001;
double A, B, C, D;
double Bsearch(double l, double r, double k, double eps, double (*GetVal)(double, double))
{
double mid;
//printf("l %.2f r %.2f\n", l, r);
while(r - l > eps)
{
//printf("l %.2f r %.2f\n", l, r);
mid=(l+r)/2.000;
if(GetVal(l, mid) < k)
r = mid;
else
l = mid;
}
return mid;
}
double Func(double x)
{
return A * x * x * x + B * x * x + C * x + D;
}
double GetVal(double l, double r)
{
return Func(l) * Func(r);
}
int main()
{
cin>>A>>B>>C>>D;
int ansCnt = 0;
double ans[4];
for(double l = -100; l <= 99; l += 1)
{
double r = l + 1;
//printf("l %.2f r %.2f\n", l, r);
if(Func(l) == 0)
ans[++ansCnt] = l;
else if(Func(l) * Func(r) < 0)
{
//printf("ok\n");
ans[++ansCnt] = Bsearch(l, r, 0, EPS, GetVal);
}
}
//printf("%.2f %.2f %.2f\n", ans[1], ans[2], ans[3]);
//sort(ans+1, ans + 3 + 1);
for(int i=1; i<=ansCnt; i++)
printf("%.2f ", ans[i]);
return 0;
}
以上是关于luogu1024 一元三次方程求解的主要内容,如果未能解决你的问题,请参考以下文章