codeforces1359C. Mixing Water

题目链接

现有两水源,一个热水h度,另一个凉水c度,然后你往体积无限的桶里一瓢热的一瓢凉的倒,问倒几瓢离t度最接近


显然这题答案只有两种,要么是2,要么 2 n + 1 2n+1 2n+1

 证明如下:
 - 当混合了$2n$次之后,温度

t d = n ( h + c ) 2 n = h + c 2 t_d = \frac{n(h+c)}{2n}=\frac{h+c}{2} td=2nn(h+c)=2h+c

 可见偶数次混合后温度恒定

 - 当混合了$2n+1$次后,温度

t d = n ( h + c ) + h 2 n + 1 t_d = \frac{n(h+c)+h}{2n+1} td=2n+1n(h+c)+h

其中$t_d(n+1)-t_d(n)<0$故混合温度单调递减且收敛于$\frac{h+c}{2}$

综上可知:

  • 对于 t ≤ h = c 2 t\leq \frac{h=c}{2} t2h=c时,混合2次即可
  • t ≥ h = c 2 t\geq \frac{h=c}{2} t2h=c时需要计算次数

下面就第二种情况,即答案为 2 n + 1 2n+1 2n+1的情况做说明:
根据 t d t_d td的单调性可知,对于 ∀ t > h + c 2 \forall t>\frac{h+c}{2} t>2h+c必然存在唯一解;且借助单调性,可以用二分进行更高效的查找。但由于涉及浮点运算,所以注意精度或将double换为longlong

最后解释一下 为什么double存在精度问题

#pragma GCC diagnostic error "-std=c++11"
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return

#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;

template<class T> void _deb(const char *name,T val){
    cout<<name<<val<<endl;
}


int t;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    cin>>t;
    while(t--){
        double h,c,t;
        cin>>h>>c>>t;
        if((int)t<=(int)((h+c)/2)){
            cout<<2<<endl;
            continue;
        }

        int inf=0,sup=6e5;
        while(inf+1<sup){
            int mid=inf+(sup-inf)/2;
            double n=mid*2+1;

            double tem=((h+c)*mid+h)/n;
            if(tem<t)
                sup=mid;
            else
                inf=mid;
        }
        double abs1=abs(t-((h+c)*inf+h)/(2*inf+1));
        double abs2=abs(t-((h+c)*sup+h)/(2*sup+1));
        if(abs1-abs2<1e-15)
            cout<<2*inf+1<<endl;
        else
            cout<<2*sup+1<<endl;
    }

    re 0;
}

但是看过答案之后,终究还是感叹于自身的zz,能O(1)算出来的东西为啥还得二分再找呢。。。
我们已知混合了 2 n + 1 2n+1 2n+1次后的温度为
t d = n ( h + c ) + h 2 n + 1 t_d = \frac{n(h+c)+h}{2n+1} td=2n+1n(h+c)+h
t ≥ h + c 2 t\geq \frac{h+c}{2} t2h+c时,不难求出混合后第一次小于t的次数 2 i + 1 2i+1 2i+1
t d = i ( h + c ) + h 2 i + 1 ≤ t t_d =\frac{i(h+c)+h}{2i+1} \leq t td=2i+1i(h+c)+ht
且这个函数是单调递减的,所以答案就在 2 i + 1 2i+1 2i+1 2 ( i − 1 ) + 1 2(i-1)+1 2(i1)+1之中,只需要单独计算并比较差值即可

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值