题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5105

题目意思:给出一个6个实数:a, b, c, d, l, r。通过在[l, r]中取数 x,使得这个函数 f(x)= |a∗x3+b∗x2+c∗x+d| 最大。

我一开始做的时候,很天真的认为数据量这么小,一个一个试,暴力搜就肯定能得到答案啦。但是一个很严重的问题是,x 没有说是实数还是整数,所以枚举根本不可行。

  于是就联想到应该使用高中求一元三次方程的方法来做。我当时是直接从 f(l), f(r),f(x1),f(x2)(x1、x2代表方程两个根)中选择最大的来输出,但是没有考虑是否在[l, r]范围内,竟然过了,那个开心啊。可想而知最后被 hack 了,连终评都到达不了,泪~~~

  后来认认真真复习了具体求解方法,于是很正规地做:对ax^3 + bx^2 + c*x + d求导,得到一元二次方程 3ax^2 + 2bx + c,用delta(那个高中经常用到的三角形Δ)讨论根的情况,画出二次函数图象,根据单调性再画出原函数大致走向,再讨论根是否在区间[l, r]上来选择应该输出哪个f()。前前后后做了31次。那 30 次当中,知道自己很多的不足:

(1)竟然用 abs 来求浮点数绝对值,实际上是用 fabs!

(2)浮点数跟 0 比较是不可行的,要设定一个可接受的误差 eps,例如为1e-9,如果 < eps 就代表是 < 0 的。

(3)在做 delta 运算之前,漏了 a == 0(对应代码中 fabs(a) < eps) 的判断,这关乎到根存不存在的问题: 如果 b < eps(表示 b == 0),就代表无解啦,否则就有一个根 x = (-c) / (2b)

(4)最最致命的一点,就是按传统解题步骤做!今天在课上终于想明白为什么这样中规中矩做是不可行的,两天的努力没有白费了。试想下,这样做的情况非常多!

  举个例子吧,假设我们已经知道 a != 0 啦,很自然地进行delta讨论啦,假设讨论到 delta > 0(其实delta = 0可以归为该类情况) 的情况,也就是有x1, x2两个根啦。然后根据在 x 坐标轴以上表示原函数递增,以下原函数递减,最后对应到原函数(ax^3 + bx^2 + c*x + d)画出大致走向,再根据 x 的位置来判断是否应该计算f(x)(包含f(x1), f(x2)),最后选出f(x), f(l),f(r)最大的那个输出。真的是复杂到不能再复杂啦。

我当时就在想为什么是错的,因为原函数不是单纯的 ax^3 + bx^2 + c*x + d,而是这个东西的绝对值!绝对值意味着这个东西的最小值或者最大值就是答案。而我常规做的,是非绝对值的情形,所以势必会漏了不容易觉察的情况。

那么最简单,最靠谱,最正确的方法就是,除了那种 a == 0 && b == 0 没根(不用算x)的情况,其他都需要算f(x),然后选出最大的,前提是 x 在 [l, r]之间。

  这里补充说明一点,为什么我说的进行到 delta 判断中,可以将 delta < 0 与 delta >= 0 一并讨论,因为始终只会算出 x 在 [l, r]的 f(x),也就是不在或者不存在(对应delta < 0)的话就不计算(函数是返回-1),那么delta < 0 其实就是选择f(l)、 f(r)较大的一个输出。至于delta = 0,虽然只有一个根,即x1, x2相等,也不影响合并。

辛苦读者看我这篇长篇大论,不过通过这题真的学到很多,多想一个为什么一定会有所进步的!^_^ !

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std; const double eps = 1e-;
double a, b, c, d, l, r; double get_max(double x, double y)
{
if (x > y)
return x;
return y;
} double cal(double x)
{
if (x >= l && x <= r) // 前提是在[l, r] 之间
return fabs(a*x*x*x + b*x*x + c*x + d);
return -;
} int main()
{
while (scanf("%lf%lf%lf%lf%lf%lf", &a, &b, &c, &d, &l, &r) != EOF)
{
double fl = cal(l);
double fr = cal(r);
double ans = get_max(fl, fr); if (fabs(a) < eps) // a == 0
{
if (fabs(b) < eps) // b == 0,无解
printf("%.2lf\n", ans);
else
{
double x = -c/(*b); // 导数为一次函数,原函数为二次函数
printf("%.2lf\n", get_max(ans, cal(x)));
}
}
else // delta 环节
{
double delta = *b*b - *a*c;
delta = sqrt(delta);
double x1 = (-*b - delta) / (*a);
double x2 = (-*b + delta) / (*a);
double tans = get_max(cal(x1), cal(x2));
printf("%.2lf\n", get_max(ans, tans));
}
}
return ;
}

BestCoder18 1002.Math Problem(hdu 5105) 解题报告的更多相关文章

  1. BestCoder12 1002.Help him(hdu 5059) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5059 题目意思:就是输入一行不多于 100 的字符串(除了'\n' 和 '\r' 的任意字符),问是否 ...

  2. BestCoder3 1002 BestCoder Sequence(hdu 4908) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4908 题目意思:给出 一个从1~N 的排列你和指定这个排列中的一个中位数m,从这个排列中找出长度为奇数 ...

  3. BestCoder17 1002.Select(hdu 5101) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5101 题目意思:给出 n 个 classes 和 Dudu 的 IQ(为k),每个classes 都有 ...

  4. BestCoder6 1002 Goffi and Squary Partition(hdu 4982) 解题报告

    题目链接:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?pid=1002&cid=530 (格式有一点点问题,直接粘 ...

  5. BestCoder22 1002.NPY and arithmetic progression(hdu 5143) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5143 题目意思:给出 1, 2, 3, 4 的数量,分别为a1, a2, a3, a4,问是否在每个数 ...

  6. BestCoder20 1002.lines (hdu 5124) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5124 题目意思:给出 n 条线段,每条线段用两个整数描述,对于第 i 条线段:xi,yi 表示该条线段 ...

  7. BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5087 题目意思:找出第二个最长递增子序列,输出长度.就是说,假如序列为 1 1 2,第二长递增子序列是 ...

  8. BestCoder15 1002.Instruction(hdu 5083) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5083 题目意思:如果给出 instruction 就需要输出对应的 16-bit binary cod ...

  9. BestCoder10 1002 Revenge of GCD(hdu 5019) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5019 题目意思:给出 X 和 Y,求出 第 K 个 X 和 Y 的最大公约数. 例如8 16,它们的公 ...

随机推荐

  1. 写在SDOI2016Round1前的To Do List

    理性的整理了一下自己的不足. 计算几何啥都不会,字符串类DP毫无练习,数据结构写的不熟,数论推不出式子,网络流建模常建残: 需要达成的任务: 一.网络流: 熟练网络流的板子(之前一直仰慕zkw费用流, ...

  2. UOJ35 后缀数组(模板)

    #35. 后缀排序 这是一道模板题. 读入一个长度为 nn 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置.位置编号为 1 ...

  3. Visio绘制时序图

    用visio建立时序图 1.选择模版 2.常见符号 时序图创建步骤 1.确定交互过程的上下文: 2.识别参与过程的交互对象: 3.为每个对象设置生命线: 4.从初始消息开始,依次画出随后消息: 5.考 ...

  4. hihocoder #1285 智力竞赛

    传送门 总结: 1.仔细读题 2.仔细分析复杂度 3.不要想当然,乱下结论 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi.小Ho还有被小Hi强拉来的小Z,准备组队 ...

  5. 【js】JSON.stringify 语法实例讲解

    语法:  JSON.stringify(value [, replacer] [, space]) value:是必选字段.就是你输入的对象,比如数组,类等. replacer:这个是可选的.它又分为 ...

  6. jquery------添加jQuery对象方法

    my.js $(document).ready(function(){ (function($){ $.fn.swapClass=function(class1,class2){ if(this.ha ...

  7. ON THE EVOLUTION OF MACHINE LEARNING: FROM LINEAR MODELS TO NEURAL NETWORKS

    ON THE EVOLUTION OF MACHINE LEARNING: FROM LINEAR MODELS TO NEURAL NETWORKS We recently interviewed ...

  8. 用过SQL语句获取织梦DedeCMS每个栏目各有多少文章

    我对SQL语句不是很精通,这个SQL调用语句是我在一个模板里面看到了,特来和大家分享,大家在制作模板的过程中有需要可以用得到.       显示效果: 共有会员:31 名       本月更新:39 ...

  9. tcpdump wireshark 实用过滤表达式(针对ip、协议、端口、长度和内容) 实例介绍

    tcpdump wireshark 实用过滤表达式(针对ip.协议.端口.长度和内容) 实例介绍 标签: 网络tcpdst工具windowslinux 2012-05-15 18:12 3777人阅读 ...

  10. 点击label时click事件被触发两次的坑

    今天帮群里的朋友看一段代码的时候偶然间遇到一个label的坑,点击label的时候,监听的click事件被执行两次: 具体代码如下: <div id="test"> & ...