P1024 一元三次方程求解题解

题目传送门

浮点数二分的模板

https://www.acwing.com/problem/content/792/

C++ 代码

#include <bits/stdc++.h>

using namespace std;

const double eps = 1e-8;   // eps 表示精度,取决于题目对精度的要求,6位小数,就是1e-8,5位就是1e-7

//三次方根:浮点数的二分,说白了就是个试,找到了算,但不是傻找,而是一半一半找。
int main() {
    double x;
    cin >> x;
    double l = -10000; //这个边界有意思,注意左右边界
    double r = 10000;
    while (r - l > eps) { //浮点数差逼近了一个极小值,表示找到了相似值
        double mid = (l + r) / 2;
        if (mid * mid * mid >= x) r = mid; //计算三次方根
        else l = mid;
    }
    printf("%.6lf\n", l); //默认保留6位小数
    return 0;
}

本题:
1、值的范围 \([-100,100]\),可以用来遍历,用整数\(i\)来遍历,根就在它附近。
2、任意两根之差不小于1,可以处理完一个\(i\)后,再一个可以直接用来加1进行再次探测。
3、计算公式:

double f(double x) {
    return a * x * x * x + b * x * x + c * x + d;
}

4、精度控制,一般浮点数二分 1e-8足够。
5、注意题目中的提示:

这样,就不用每个可能区间全部都去深度二分了,减少了大量的计算。
6、最关键的:
特判!!!因为可能边界值就是答案,比如整数5,这时再去二分[5,6]就没有意义,注意特判!!!

#include<bits/stdc++.h>

using namespace std;

const double eps = 1e-8;
double a, b, c, d;

//方程
double f(double x) {
    return a * x * x * x + b * x * x + c * x + d;
}

int main() {
    //输入
    cin >> a >> b >> c >> d;
    double x, y, mid;

    for (int i = -100; i <= 100; i++) {
        x = i, y = i + 1;//两个指针
        //边界
        if (f(x) == 0) {
            printf("%.2f ", x);//如果符合条件则直接输出
            continue;
        }
        //如果其中有解就开始二分
        if (f(x) * f(y) < 0) { //题目中有提示
            //精度要求
            while (y - x >= eps) {
                mid = (x + y) / 2;
                if (f(x) * f(mid) <= 0)y = mid;//判断解在哪个区间
                else x = mid;
            }
            printf("%.2f ", x);
        }
    }
    return 0;
}

posted @ 2021-07-23 10:32  糖豆爸爸  阅读(71)  评论(0编辑  收藏  举报
Live2D