【题目链接】
ybt 1085:球弹跳高度的计算
OpenJudge NOI 1.5 20:球弹跳高度的计算
【题目考点】
1. 循环
【解题思路】
1. 使用循环描述球的弹跳过程
写法1:以一次弹起后下落为一个周期
设sum表示球经过的总距离,h是下一次弹起的高度
一开始第1次下落,高度h,sum为h。
循环控制变量i表示第几次弹起,每次循环是先弹起后下落,弹起和下落的高度为上次下落的高度h的二分之一,所以h /= 2
,每次弹起落下的距离为2h。
第9次弹起后下落,经过的总距离为第10次弹起也就是第10次落地前经过的总距离。下一次第10次弹起时,弹起高度要再次减半,所以弹起高度为h/2。
写法2:以一次下落后弹起为一个周期
设sum表示球经过的总距离,h是这一次下落的高度
循环控制变量i表示第几次下落,每次循环是先下落后弹起,下落高度为h,弹起高度减半,h变为h/2。
第9次下落弹起后,球还需要下落h距离才是第10次落地时球经过的距离。所以总距离为sum+h,第10次弹起时,高度再次减半,为h/2。
2. 数学计算
分析各次落地前弹跳的距离
设球的初始高度是
h
h
h
- 第1次下落 h h h,第1次落地,第1次反弹 h 2 \frac{h}{2} 2h
- 第2次下落 h 2 \frac{h}{2} 2h,第2次落地,第2次反弹 h 4 \frac{h}{4} 4h
- 第3次下落
h
4
\frac{h}{4}
4h,第3次落地,第3次反弹
h
8
\frac{h}{8}
8h
… - 第i次下落
h
2
i
−
1
\frac{h}{2^{i-1}}
2i−1h,第i次落地,第i次反弹
h
2
i
\frac{h}{2^i}
2ih
第10次落地之前,共经历了10次下落,9次反弹,将下落和反弹的距离加和,设总距离为s:
s = h + h 2 + h 2 + h 4 + h 4 + . . . + h 2 9 + h 2 9 = h + 2 ( h 2 + h 4 + . . . + h 2 9 ) = h + h + h 2 + h 4 + . . . + h 2 8 \begin{aligned} s &= h + \frac{h}{2} +\frac{h}{2} + \frac{h}{4}+\frac{h}{4}+...+\frac{h}{2^{9}}+\frac{h}{2^{9}}\\&= h + 2(\frac{h}{2} + \frac{h}{4} + ... +\frac{h}{2^{9}}) \\ &= h + h + \frac{h}{2} + \frac{h}{4} + ... +\frac{h}{2^{8}} \end{aligned} s=h+2h+2h+4h+4h+...+29h+29h=h+2(2h+4h+...+29h)=h+h+2h+4h+...+28h - 根据等比序列加和公式:
S n = a 1 1 − q n 1 − q S_n = a_1\frac{1-q^n}{1-q} Sn=a11−q1−qn
可以得到
s = h ( 1 + 1 + 1 2 + 1 4 + . . . + 1 2 8 ) = h ( 1 + 1 − ( 1 2 ) 9 1 − 1 2 ) = h ( 3 − 1 2 8 ) \begin{aligned} s &= h(1 + 1 + \frac{1}{2} + \frac{1}{4} + ... +\frac{1}{2^{8}}) \\ &=h(1 + \frac{1-(\frac{1}{2})^9}{1-\frac{1}{2}})\\ &= h(3 - \frac{1}{2^8}) \end{aligned} s=h(1+1+21+41+...+281)=h(1+1−211−(21)9)=h(3−281) - 根据规律可知,第10次反弹的距离为: h 2 10 \frac{h}{2^{10}} 210h
【题解代码】
解法1:使用循环描述球的运行过程
- 写法1:以一次弹起后下落为一个周期
#include <bits/stdc++.h>
using namespace std;
int main()
{
double h, sum;//h:初始高度 sum:球经过的总距离
cin >> h;
sum = h;//sum:总距离初始值设为h,即第一次下落的距离为h
for(int i = 1; i <= 9; ++i)//i表示第几次弹起
{
h /= 2;//落地后弹跳高度变为原来的一半。运算后h为第i次弹起的高度
sum += 2 * h;//球弹起距离h,下落距离h,经过2h距离后再次落地。运行这句后,此时sum表示第i+1次弹起前小球经过的距离
}
cout << sum << endl << h/2 << endl;//此时sum为第10次弹起前也就是第10次落地时经过的距离,h为第10次下落的高度,第10次弹起的高度应该为h/2
return 0;
}
- 写法2:以一次下落后弹起为一个周期
#include <bits/stdc++.h>
using namespace std;
int main()
{
double h, sum;//h:初始高度 sum:球经过的总距离
cin >> h;
for(int i = 1; i <= 9; ++i)//i表示第几次下落
{
sum += h;//第i次下落距离h
h /= 2;//落地后弹跳高度变为原来的一半。
sum += h;//球弹起距离h
}
cout << sum+h << endl << h/2 << endl;//此时sum为第10次下落前经过的距离,加上h为第10次下落的高度,就是经过的总距离。第10次弹起的高度应该为h/2
return 0;
}
解法2:根据数学
推导输出结果
在上述【解题思路】中得到结论:
球弹跳的总距离:
h
(
3
−
1
2
8
)
h(3 - \frac{1}{2^8})
h(3−281)
第10次弹起的距离:
h
2
10
\frac{h}{2^{10}}
210h
#include <bits/stdc++.h>
using namespace std;
int main()
{
double h;
cin>>h;
cout<<h * (3 - 1 / pow(2, 8))<<endl<<h / pow(2, 10)<<endl;
return 0;
}