現有兩水源,一個熱水h度,另一個涼水c度,然後你往體積無限的桶裏一瓢熱的一瓢涼的倒,問倒幾瓢離t度最接近
顯然這題答案只有兩種,要麼是2,要麼。
證明如下:
- 當混合了$2n$次之後,溫度
可見偶數次混合後溫度恆定
- 當混合了$2n+1$次後,溫度
其中$t_d(n+1)-t_d(n)<0$故混合溫度單調遞減且收斂於$\frac{h+c}{2}$
綜上可知:
- 對於時,混合2次即可
- 時需要計算次數
下面就第二種情況,即答案爲的情況做說明:
根據的單調性可知,對於必然存在唯一解;且藉助單調性,可以用二分進行更高效的查找。但由於涉及浮點運算,所以注意精度或將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)算出來的東西爲啥還得二分再找呢。。。
我們已知混合了次後的溫度爲
當時,不難求出混合後第一次小於t的次數
且這個函數是單調遞減的,所以答案就在與之中,只需要單獨計算並比較差值即可