23年蓝桥杯 ———— 阶乘求和
5.阶乘求和 - 蓝桥云课
要求如下:
怎么说呢,写了1个小时也没写出来,我丢,这题是真的逆天,真没想到先把计算一下每个数的阶乘,看了人家的解析,我还纳闷呢,第40个是0 我看了半天也没想明白这他喵的怎么能是0呢,后来才反应过来,是第40个数 40 !保留9位数是0,我丢
deepseek如是说:
嗯,这道题是要求计算从1!到202320232023!的和的末尾9位数字。首先,我想到直接计算这么大的阶乘和显然是不现实的,因为阶乘增长得非常快,数值会变得极大,远远超出计算机的处理能力。因此,必须找到一种巧妙的方法来简化计算。
首先,我回忆了模运算的性质。题目要求的是末尾9位数字,也就是结果对10^9取余后的值。所以,应该可以在计算每个阶乘时,直接对10^9取余,避免数值过大。不过,这样处理是否正确呢?
然后,我想到阶乘的末尾会有很多零。例如,10!的末尾有两个零,而更大的阶乘会有更多的零。当某个阶乘的末尾零的数量达到或超过9个时,这个阶乘对10^9取余的结果就是0,并且之后更大的阶乘也会继续对10^9取余为0,因为阶乘中会有更多的因子2和5,从而产生更多的零。因此,当某个阶乘之后的所有项对10^9的余数都是0时,后续的计算就可以停止了。
接下来,我需要确定从哪个阶乘开始,余数变为0。例如,40!的末尾有多少个零呢?计算末尾零的数量取决于阶乘中因子2和5的数量,因为每个零都是由一个2和一个5相乘得到的。在阶乘中,因子5的数量通常比因子2少,所以末尾零的数量由因子5的数量决定。计算40!中因子5的数量:40/5 + 40/25 = 8 + 1 = 9个。因此,40!的末尾有9个零,对10^9取余的结果是0。之后的阶乘,比如41!、42!等,末尾的零数量更多,所以它们的余数也都是0。因此,只需要计算到40!即可,后面的项对总和没有贡献。
现在,我需要验证这个思路是否正确。编写一个简单的Java程序,计算每个阶乘对10^9的余数,当余数变为0时停止,并累加这些余数,最后输出总和对10^9的余数。这样就能得到正确的末尾9位数字。
在编写代码时,需要注意的是,每次计算阶乘时都要及时取余,避免数值溢出。例如,使用长整型变量来保存阶乘和总和,并在每次乘法后立即取余,这样可以确保数值不会超出长整型的范围。
此外,输出结果时需要格式化输出,确保即使结果不足9位,也要用前导零补足。例如,如果总和是12345678,应该输出012345678,但题目提示答案的首位不为0,所以实际结果不会有前导零的问题,但代码中还是需要处理这种情况。
最后,运行代码,验证结果是否符合预期。例如,当计算到40!时,程序应该停止,并且累加的结果应该是正确的末尾9位数字。通过实际运行代码,可以得到具体的数值结果,确保答案的正确性
我试了一下:
package zhen23;
import java.math.BigInteger;
/**
* @author zb
// * 什么世阶乘
* date2025/3/16 14:07
*/
public class L3500 {
public static void main(String[] args) {
long sum = 0;
for (long i = 1; i <= 40L; i++) {
long jie = 1;
for (int j = 1; j <= i; j++) {
jie = (long) ((jie*j)%(1e9));
}
System.out.println(i+"!等于 :"+jie);
sum = (long) ((jie+sum) % (1e9));
// sum %= (1e9);
}
System.out.println(sum);
}
}
运行之后的1-40的阶乘
我们每个阶乘计算结果都要对(1e9)取余数,因为只保留末尾9位数,10位数及以上就都不管了
40的阶乘%(1e9)=0 ,也就是说之后每个大于40 的数的阶乘%(1e9)都等于0
41!%(1e9)=41* 40! = 41 * 0 = 0
42!%(1e9)=40 ! * 41 * 42 = 0
一直到202320232023!对(1e9)取余数都是0
39!%(1e9)是最后一个不等于0 的,
所以的话那么1!+.....+39!+40! + ......+202320232023! = 1+......+39!+0+0+0+0+......+0
所以我们可以直接从1!累加到39!就行,就是答案