数学、细心

这题也是个教训!! 唉,我真是一直都被狠狠地教训着!!!

题意:
你有一个无限大的水桶,有无限杯热水温度为h,有无限杯凉水温度为c,给你一个温度t
你先倒热水一杯,再倒凉水一杯,求你最少到多少杯后能最大的接近温度t?即|t - m|最小
其中m为混合出的温度.m为凉水热水的混合平均值

数据范围:1<=c<h<=1e6, c<=t<=h

这题不难,确实不难。
我们将杯数n分为奇数偶数讨论,偶数的话温度恒为(h+c)/2
这样我们不妨令杯数为最小的2。
那么关键是杯数为奇数时的情况了。
杯数为奇数时温度为((k+1)h+kc)/(2k+1) n = 2k+1 ,k大于等于0,记为C(k)
对这个式子化简可以看到为 (h+c)/2 + (h-c)/(4k+2) > (h+c)/2
那么当t<=(h+c)/2时,cout<<2<<endl;
当t>(h+c)/2时,我们计算C(k) = t,取k的整数。
然后比较|C(K)-t| 与 |C(k+1)-t| 与 |(h+c)/2-t|
就可以了。谁小答案是谁.若相等则看谁的杯数小是谁
其实可以不比较(h+C)/2的,当然比了 答案也不会有变化。
我们,可以用排序比较的。

但这一题中我被坑的地方是在计算|C(k) - t|时的情况。
我在一开始时是这样做的:

fabs(((k+1)*h+k*c)/(2*k+1)-t)

但是我看了一下数据范围,1<=c<h<=1e6, c<=t<=h
很快我发现了不应该这样写,这可能会导致k*h过大,溢出,
因此,我将其转为:

fabs((h+c)/2.0 + (h - c) / (4 * k + 2) - t)

自信满满的我将其提交上去了,WA,哈哈哈哈哈哈。。。。。
而且一直都是在test4时错了,怎么都找不到哪里错的。。。。。。。。烦烦烦!!

后来,测试用例开放,我经过调试,问人。。。才终于知道自己错哪了。。
看到上面的式子吗?将其改一下:

fabs((h+c)/2.0 - t + (h - c) / (4 * k + 2))

没错,者的就就是这样改一下,答案就正确了。
原因是,double 的精度问题,当k达到一定程度时,小数点后位数太多,double不够用,
因此要把和(h+c)/2,0相近的t剪掉,他两人先运算,避免运算误
差太大。。。。

真的是学到了!!!!!

代码如下,注意细节:

#include<algorithm>;
#include<iostream>;
using namespace std;

#define foru(i, a, b) for(auto i=(a);i<(b);++i)
#define ford(i, a, b) for(auto i=(a);i>(b);--i)
#define maxn 10005
typedef long long ll;

inline int read() {
    char ch = getchar();
    int f = 1, x = 0;
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
    return f * x;  
}

int main() {
    int T = read(), h, c, t, ans;
    double mid, temp;
    while (T--) {
        h = read(), c = read(), t = read();
        mid = (h + c) / 2.0;
        if (h <= t)
            cout << 1 << endl;
        else if (mid >= t)
            cout << 2 << endl;
        else {
            ans = ((h - mid) * 1.0 / (t - mid) - 1) / 2;
            if (fabs(mid - t + (h - mid) * 1.0 / (2.0 * ans + 1)) <= fabs(mid - t + (h - mid) * 1.0 / (2.0 * ans + 3)))
                cout << 2 * ans + 1 << endl;
            else
                cout << 2 * ans + 3 << endl;
        }
    }
    return 0;
}

亏我死磕了一晚上。。。。。。。。