欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

luogu1024 一元三次方程求解

程序员文章站 2022-05-09 09:57:06
...

题目大意

已知一元三次方程\(ax^3+bx^2+cx+d=0\)

  1. 有且只有3个根
  2. \(\forall x, x\in[-100,100]\)
  3. \(\forall x_1,x_2,|x_1-x_2|\geq1\)
  4. 定理:令\(f(x)=ax^3+bx^2+cx+d\),则\(f(l)f(r)<0\Leftrightarrow \exists x\in [l,r],使得f(x)=0\)

思路

从拿到题开始我们很容易想到二分。二分求点都是求一个点,包含该点的区间具有某一特定性质,不包含这个点的区间不具有这一特定性质。“区间的特定性质”便是性质4。但是怎么保证区间中只有一个点呢?由性质3可得每个长度为1的区间最多有一个解。因此我们对于每个满足性质4的长度为1的区间二分即可。

注意

  • 长度为1的区间内的函数图象不一定单调,所以\(f(\frac{l+r}{2})\)不具有任何代表性。
#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;
}