【codevs1038 一元三次方程求解】分治

这道题WA了将近两天!!!!!我最近一写题就WA,一WA就一天!!!!简直有毒。

题目里说了根的范围是 (100,100)  ,而且根与根之差的绝对值>=1,那么思想就是把 (100,100)  分成 [100,99]  [99,98]  ……这样一个一个的区间,看看区间端点a、b,f(a) * f(b)是否<0,是的话就对这个区间二分,找出答案。

这道题不能直接二分,因为它不是一个单调区间。超超超超超级棒的ilern跟我说如果是单调区间就可以直接二分,如果不是的话就把它划分成几个单调区间来二分。

知道了思想之后还是WA,原因是double用的不熟练。
double类型,输入用%lf, 输出是%.2lf, 2是要求保留2位小数。
float用%f输入,%.2f输出。
printf(“%03d”, 25)的结果是025%3d的结果是25。就可以控制输出的格式。

需要注意的是用double需要注意精度,比较和常数的大小啊啥的都要允许有误差。可以定义 const double EPS = 1e-7;

#include <cstdio>
#include <cmath>

const double EPS = 1e-7;

double a, b, c, d, x1, x2, x3, l[4], r[4];

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

double find(double l, double r)
{
    //printf("find(%lf, %lf)\n", l, r);
    if (fabs(l - r) <= EPS || fabs(f((l + r) / 2)) <= EPS)
    {
        return (l + r) / 2;
    }
    else
    {
        if (f(l) * f((l + r) / 2) <= EPS)
        {
            return find(l, (l + r) / 2);
        }
        else
        {
            return find((l + r) / 2, r);
        }
    }
}

bool have(double a, double b)
{
    //double fa = f(a), fb = f(b);
    //printf("f(a = %.3lf) = %.3lf, f(b = %.3lf) = %.3lf\n", a, fa, b, fb);
    if (f(a) * f(b) <= EPS)
    {
        return true;
    }
    else
    {
        return false;
    }
}

int main()
{
    scanf("%lf %lf %lf %lf", &a, &b, &c, &d);
    int cnt = 0;

    for (int i = -100; i < 100; i++)
    {
        double j = i + 1 - EPS;
        if (have(i, j) == true)
        {
            l[cnt] = i;
            r[cnt] = j;
            cnt++;
        }
    }

    x1 = find(l[0], r[0]);
    x2 = find(l[1], r[1]);
    x3 = find(l[2], r[2]);

    printf("%.2lf %.2lf %.2lf\n", x1, x2, x3);
    return 0;
}

第一种。。。。。。我自己的bug找不出来,然后很表脸的去找了【dalao】debug,然后输出中间变量的调试方法get√【最近用gdb就只会设断点,跑跑跑,都不会输出中间变量了= =】
有的时候要加fabs【实数去绝对值,整数是abs】【例如f(d) == 0就要改成fabs(f(d)) <= EPS】,但是有的时候不用加。

#include <cstdio>
#include <cmath>

const double EPS = 1e-7;
double a, b, c, d, x1, x2, x3;

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

bool have(double a, double b)
{
    // double fa = f(a), fb = f(b);
    // printf("f(a = %.3lf) = %.3lf, f(b = %.3lf) = %.3lf\n", a, fa, b, fb);

    if (f(a) * f(b) <= EPS)
    {
        return true;
    }
    else
    {
        return false;
    }
}

void find(double l, double r)
{
    //printf("find(%lf, %lf)\n", l, r);
    double d = (l + r) / 2;
    if ((r - l) <= EPS || fabs(f(d)) <= EPS)
    {
        printf("%.2lf ", d);
        return;
    }
    else
    {
        if (f(l) * f(d) <= EPS)
        {
            find(l, d);
        }
        else
        {
            find(d, r);
        }
    }
}

int main()
{
    scanf("%lf %lf %lf %lf", &a, &b, &c, &d);

    for (int i = -100; i < 100; i++)
    {
        if (have(i, i + 1 - EPS) == true)
        {
            find(i, i + 1 - EPS);
            //printf("%d\n", i);
        }
        else continue;
    }
    return 0;
}

第二种。。。。。。【然而并没有太大的差别(:з」∠)
这个WA了很久的原因是主函数里i在循环的时候如果解是整数,就当i= i和i+ 1的时候都符合have,它都会输出。然后把边界定成(i, i + 1 - EPS)就行了。

【我还是太差了,这道并不算很难的题写了好久,有的bug自己还看不出来qnq】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值