题目描述
小L目前正在他的实验室里研究高能粒子。他发现了一种神奇的粒子,小L称其为L粒子。L粒子拥有着 n n n个价位,第 i i i个价位对应存储着大小为 A i A_i Ai的势能,并且 A i A_i Ai互不相同。现在小L想要做一个实验来研究L粒子的性质,他首先会选出L粒子的三种价位 x , y , z ( A x < A y < A z ) x,y,z(Ax<Ay<Az) x,y,z(Ax<Ay<Az),一开始L粒子处于价位 x x x,然后小L会给L粒子充能,使其价位升高至 z z z,然后控制L粒子释放能量,使其价位跌落至 y y y,最后L粒子会自发地流失能量,使其价位回到 x x x。为了尽可能地利用能量,小L希望这个实验的能量利用效率 最大。但由于实验设备过于老旧,小L并不能给L粒子充超过 m m m能量(也就是说 A z − A x Az-Ax Az−Ax不能大于 m m m),否则实验仪器会损坏。小L想知道他做实验的能量利用效率最大是多少,但他还有别的事情要忙,于是他把这个问题交给了你。
输入
第一行一个整数
T
T
T,表示数据组数。
接下来每组数据第一行两个整数
n
,
m
n,m
n,m,意义如题面中所述。
第二行
n
n
n个整数,第i个表示L粒子价位
i
i
i存储的势能
A
i
A_i
Ai.
输出
对于每组数据输出一行一个实数,表示最大的效率,如果小L不能完成实验,输出-1.
你与标准答案的绝对误差不能超过10^(-9)。
样例输入
1
5 5
1 2 5 8 9
样例输出
0.75
数据范围限制
思路
这。。。这应该是道数学题吧 (数学题太难了
效
率
=
(
z
−
y
)
/
(
z
−
x
)
效率=(z-y)/(z-x)
效率=(z−y)/(z−x),因为
(
z
−
y
)
(z-y)
(z−y)是可以运用的能量,
(
z
−
x
)
(z-x)
(z−x)是总能量。(后面的解释请dalao们自动忽略)
那为了方便求解,我们就把TA变形一下:求最小的
(
y
−
x
)
/
(
z
−
x
)
(y-x)/(z-x)
(y−x)/(z−x)。嗯~ o( ̄▽ ̄)o,这个好求多了。要保证
x
−
y
x-y
x−y最小,
z
−
x
z-x
z−x最大。先排个序 (不要问我为什么,因为要用二分,
i
i
i枚举
x
x
x,那么
y
=
a
[
i
+
1
]
y=a[i+1]
y=a[i+1]。
z
z
z是最大的一个减
x
<
=
m
x<=m
x<=m的
a
i
a_i
ai。怎么求
z
z
z呢?当然是二分啦 (废话)
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int t,n,m,a[100100];
double Gun;
int main(){
// freopen("atom.in","r",stdin);
// freopen("atom.out","w",stdout);
scanf("%d",&t);
while(t--){
Gun=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
for(int i=1;i<n-1;i++){//枚举x
int j=i+1;//a[j]=y;
int r=1,l=n;
while(r<l){
int mid=(l+r)/2+1;
if(a[mid]-a[i]>m)l=mid-1;
else r=mid;
}//二分
Gun=max(Gun,(a[r]-a[j])*1.0/(a[r]-a[i]));//(z-y)/(z-x)最大
}
if(Gun!=0)printf("%0.12f\n",Gun);
else printf("-1\n");//划重点
}
}