acwing 1381 阶乘
题目描述
N N N 的阶乘(记作 N ! N! N!)是指从 1 1 1 到 N N N(包括 1 1 1 和 N N N)的所有整数的乘积。
阶乘运算的结果往往都非常的大。
现在,给定数字 NN,请你求出 N!N! 的最右边的非零数字是多少。
例如 5 ! = 1 × 2 × 3 × 4 × 5 = 120 5!=1×2×3×4×5=120 5!=1×2×3×4×5=120 5 ! = 1 × 2 × 3 × 4 × 5 = 120 5!=1×2×3×4×5=120 5!=1×2×3×4×5=120,所以 5 ! 5! 5! 的最右边的非零数字是 2。
输入格式
共一行,包含一个整数 N。
输出格式
输出一个整数,表示 N!N! 的最右边的非零数字。
数据范围
1 ≤ N ≤ 10001 ≤ N ≤ 1000 1≤N≤10001≤N≤1000 1≤N≤10001≤N≤1000
输入样例:
7
输出样例:
4
考察点
step1:末尾为0的最终只能是由 2 ∗ 5 = 10 2 * 5 = 10 2∗5=10这种得来的,就算是 10 10 10 20 20 20 这种以0结尾的去乘以某个数得到的末尾是0的,仍然可以看作是由2和5的乘积演变而来的。因此我们只需要把包含成对的2和5的去掉就可以了。
step2:由于在for循环里同步除以了2和5,但是实际上当 i i i比较大的时候,包含2的个数要比5的多(这里证明暂无知,如果有知道的伙伴欢迎可以把链接留下来。),所以最后要再乘上 d 2 − d 5 d2-d5 d2−d5个2
step3:最后输出c
推导:
设 n ! n! n!末尾有 k k k个 0 0 0,那么题目所求的就是 ( n ! 1 0 k m o d 10 ) \left(\frac{n!}{10^k} mod 10 \right ) (10kn!mod10),而 1 0 k = 2 k ⋅ 5 k 10^k = 2^k \cdot 5^k 10k=2k⋅5k, n ! = 2 α ⋅ 5 β ⋅ p 1 m ⋅ p 2 n n! = 2^\alpha \cdot 5^\beta \cdot p_1^m \cdot p_2^n n!=2α⋅5β⋅p1m⋅p2n ,我们可以只看2和5的,其余项我们可以通过模10来处理。
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(reader.readLine());
// d2统计包含数字i包含多少个2,d5统计包含多少个5
int d2 = 0, d5 = 0, c = 1;
// 循环结束后因为2和5都被除去了,所以个位肯定不是0
for (int i = 2; i <= n; i++) {
int j = i;
// 由于一个数只要是10的倍数最后的数字一定是0,因此我们需要可以先除去为0的部分
// 又因为10以内的数字中只有2*5=10,因此我们可以将除去它的因数就可以了
while (j % 2 == 0) {
j /= 2;
d2++;
}
while (j % 5 == 0) {
j /= 5;
d5++;
}
// 得到所有不包含2和5的倍数的数的乘积的结果的个位数
c = c*j % 10;
}
// 处理多出来2的倍数,因为一个数仅仅是2的倍数但并不是5的倍数是可以省略的
for (int i = 0; i < d2- d5; i++) {
c = c*2 % 10;
}
writer.write(c + "\n");
writer.flush();
writer.close();
reader.close();
}
}