问题描述
题目
假设一个球从任意高度自由落下,每次落地后反跳回原高度的一半; 再落下, 求它在第5次落地时,共经历多少米?第5次反弹多高?
数据范围:输入的小球初始高度满足 1≤ n ≤1000 ,且保证是一个整数。
输入描述:
输入起始高度,int型
输出描述:
分别输出第5次落地时,共经过多少米以及第5次反弹多高。
注意:你可以认为你输出保留六位或以上小数的结果可以通过此题。
例子
输入:1
输出:2.875
0.03125
解决方法
package huawei;
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
double input = sc.nextInt();
double high = input;
for(int i = 0; i < 4; i++){
high += input;
input /= 2.0;
}
input /= 2.0;
System.out.println(high);
System.out.println(input);
}
}
}
该代码是牛客上面一个哥们写的,在此作为例子。我们碰到这种问题时,大部分第一想法是用循环解决,就像上面的代码一样。其实这道题还有一个不错的解法,具体代码如下:
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int height=input.nextInt();
double num1=height*Math.pow(0.5,5);
double num2=3*height-4*num1;
System.out.println(num2);
System.out.println(num1);
}
}
解题思路
这道题本质上还是一道关于等比数列的算法题,可以利用等比数列的通项公式和求和公式解决。以这道题举个例子:
假设小球从n高度掉下来,每次反跳回原来的一半,那么第一次反跳就是n0.5,第二次则是n0.5*0.5,以此类体,这就是等比数列,公比是0.5。
注意:在这道题中,首项就是初始的高度,但是第五次的反跳高度是数列中的第6项。
根据等比数列通项公式an=a1*qn-1可以算出第五次反跳的高度,转换成代码如下:
而第五次落地时经历多少米则是通过等比数列变换后计算出来的,过程思路如下:
根据等比数列的求和公式Sn=(a1-anq)/(1-q) 可以算出小球五次反跳的总高度,也就是下面图片中5条绿色线的高度。如果我们假设第五次反跳后还会掉到地面(图中x之后还有一条红线,图中没画),那么会更好的计算了,总长度就是等比数列前五项和的2倍,注意的是这里的第一项是第一次反跳的位置。假设初始高度为x,那么第一次反跳高度为x/2,将其和公比q(0.5)代入公式得:
S5=(x/2-a5*0.5)/(1-0.5)*2
算完之后,还要算上初始时掉下来的记录。因为题目要求算到第5次落地,那时还没反跳,所以减去第5次反跳的两倍距离,总距离如下:
L=S5+x-2a5
因为之前的代码中num1就是这里的a5,所以全部带进来后得:
L=(x0.5-num10.5)22-num12+x;
化简后
L=3x-4*num1
该结果对应的代码是: