试题 算法训练 P0505
资源限制
时间限制:1.0s
内存限制:256.0MB
题目
一个整数n的阶乘可以写成n!,它表示从1到n这n个整数的乘积。阶乘的增长速度非常快,例如,13!就已经比较大了,已经无法存放在一个整型变量中;而35!就更大了,它已经无法存放在一个浮点型变量中。因此,当n比较大时,去计算n!是非常困难的。幸运的是,在本题中,我们的任务不是去计算n!,而是去计算n!最右边的那个非0的数字是多少。例如,5!=12345=120,因此5!最右边的那个非0的数字是2。再如,7!=5040,因此7!最右边的那个非0的数字是4。再如,15!= 1307674368000,因此15!最右边的那个非0的数字是8。请编写一个程序,输入一个整数n(0<n<=100),然后输出n!最右边的那个非0的数字是多少。
样例输入:
7
样输出:
4
前言(在我不会这道题的时候):
1.在我还没有读完这道题的时候,我感觉挺简单的,可是当我读完了之后的时候,我才发现,的确是有点问题的,正如题目上所说的那个样子,即使是使用long去接收n!这个数字,当n增大的时候,long也会容纳不下的。
2.当我做题的时候,一遍又一遍的尝试,我依然是百思不得其解,找不到其中的奥妙之处。
3.于是乎,我在百度上搜索了一下,可是还是没有Java版本的,我只搜索到了c或者c++的,这个咱又不会,也看不懂,于是迫于无奈的我就借助一个c++代码分析了一下,终于领悟到了制敌取胜的精髓。接下来我就带你来分析一下这道题目。让你可以用任意语言把这个编译出来。
分析:
1.分析题意,它要什么,我们就找什么。它要的是n!的最右边的第一个非零数字,那我们就应该想到对n!进行取模。
2.既然,当n 增大到一定程度的时候,数据就无法存放在一个整型变量中,那么我们在一边增大的同时,再一边去减小这个数字,使这个数字可以存放如我们设置的这个整形变量中。为了防止数据增长的较大,我们在循环中先行设置一次取模,使用条件语句,在设置x /=10的好处是,防止最后x %1000之后还剩余一个零,会导致结果为零。
3.在输出之前再对x进行 取模,已经可以确保未取模的x是一个结尾不为零的整数了,此时对x进行取模10的处理,就可以得到那个个位数字了,即这就是我们所要求的的n!的最右边的第一个非零数字。输出即可。
代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); //创建键盘录入
int n = sc.nextInt(); //键盘录入一个数字n
long x = n; //创建一个long类型的变量用来存储n!(如果用int类型的话,会导致最后数据存储不下而出现异常数字)
//使用循环来计算n!
for(int i = n -1; i > 0;i --){
x *= i; //计算n * n - 1的值然后再赋值给x
if(x % 10 == 0){ //设置条件语句,x是否可以被10整除
x /= 10; //如果可以,就除以10,以防止在计算结果之前所得数据最右边包含零
x = x % 1000; //模以1000,对较大数据进行删减,确保x可以容纳下这个数字
}
}
x %= 10; //计算最终结果
System.out.println(x); //输出结果
}
}