题解 P1033 【自由落体】
zhenglier
2018-10-17 18:41:51
~~震惊,我居然在信息里推物理式子~~
其实这一题出题人比较良心,没有卡精度,用double就能过。但这题坑点还是有的。
首先让我们来推式子。
对于任意一个小球,下落的时间是一样的,从公式
$d=0.5×g×(t^2)$
可得
$t=\sqrt{\frac{d}{0.5g}}$
因为这题很良心,把$g$设为10,于是有
$t=\sqrt{\frac{d}{5}}$
因为球只要$x$轴和车有重合且在那一瞬间的高度$h_0$满足$k>=h_0>=0$小车即可接住这个球~~(居然不会被车头撞飞)~~,所以小车可以接住小球的时间$t_0$满足
$\sqrt{\frac{h}{5}}>=t_0>=\sqrt{\frac{h-k}{5}}$
然后我们就算这个时间段内小车穿过了多少个小球的$x$轴就行了,但这似乎有些难度,我们可以把它转换成求哪个编号的球小车最早可以接住,哪个编号的球小车最晚可以接住。
首先根据上面哪个公式可以得到
$t_{min}=\sqrt{\frac{h-k}{5}}$
$t_{max}=\sqrt{\frac{h}{5}}$
最早接住的球的编号$i_b$为$int(s1-t_{min}*v+l)$,记住这里要加上l,因为最早的球可以被车尾接住。
最晚接住的球的编号$i_e$为$int(s1-t_{max}*v)$。
这里的$i_b>i_e$所以答案应该是$i_b-i_e$
然后我们就有代码了
```cpp
#include<bits/stdc++.h>
using namespace std;
int n;
double h,s1,v,l,k;
int main()
{
cin>>h>>s1>>v>>l>>k>>n;
double t_max=sqrt(h/5);
double t_min=sqrt((h-k)/5);
int i_b=int(s1-t_min*v+l),i_e=int(s1-t_max*v);
cout<<i_b-i_e;
}
```
但是到这里就结束了吗?
我们可以发现这份代码连样例都过不了,因为存在一些特殊情况,如
$i_b>n$
或是
$i_e<0$
也就是我们把一些没有球的$x$轴也算成有球并被小车接住了。但这个问题其实很好解决,因为我们只要把极端的$i_b$和$i_e$处理到边界上就行了。因此,使
$i_b=min(i_b,n)$
$i_e=max(i_e,0)$
就行了。
然后就是真正的$AC$代码了
```cpp
#include<bits/stdc++.h>
using namespace std;
int n;
double h,s1,v,l,k;
int main()
{
cin>>h>>s1>>v>>l>>k>>n;
double t_max=sqrt(h/5);
double t_min=sqrt((h-k)/5);
int i_b=int(s1-t_min*v+l),i_e=int(s1-t_max*v);
i_b=min(i_b,n);i_e=max(i_e,0);
cout<<i_b-i_e;
}
```