你好\(@^0^@)/
我是潮倾,今天做的是关于阶乘的问题
嗯,这是一道填空题,所以我们肯定不可能也不能从1的阶乘真的算到202320232023的阶乘
那也太大了,溢出了,超时了
本文写两种方法
第一种
我们要想一个事情就是当我们算一个比较大的数的阶乘的时候,就比如说100,我们想有10,20,30,40,50,60,70,80,90,100乘了进去,最后都至少有11个0了,所以很大的数的阶乘后面都是0了,所以在100的阶乘之前有个数可能就是个界限,就是他的阶乘是9个0,题目中说了答案首位不为0,所以我们可以找这个界限试试。
不过其实也不用非得找到这个界限,就算100的阶乘也行,50的也行,150的也行,因为这些超过9位0的这些阶乘对我们的后九位没有影响哒
想想阶乘能出来0的:2,4,5,10,15,8,25,30,35,40
2和5 10一个零
4和15 60一个零
10 10一个零
8和25 200两个零
20
30
35和一个偶数 一个零
40
这些0加起来刚刚好九个,我是这样算的,可能大家有更好的方法(我比较笨)
也就是说40的阶乘是9个0,他的阶乘算出来一定是??????000000000这样的,而39的阶乘是?????00000000
为了不让我们的数据溢出,我们应该算的时候进行取余,先看一下代码吧
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
// 请在此输入您的代码
long long sum=0,z=1;
for(long long n=1;n<=39;n++)
{for(long long i=1;i<=n;i++)
{
z*=i;
z%=1000000000;
}
sum+=z;
sum%=1000000000;
z=1;
}
printf("%lld",sum);
return 0;
}
{for(long long i=1;i<=n;i++)
{
z*=i;
z%=1000000000;
}
这是求n的阶乘,但是每一次乘的时候我们都对z进行了9位的取余,保证我们的后9位永远是对的,溢出就代表我们的数坏了
放一个错误的代码,就是下面这段
{for(long long i=1;i<=n;i++)
{
z*=i;
}
z%=1000000000;
这个是错的,是因为假如说我们的n是35,
1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20*21*22*23*24*25*26.......可能还没有乘到35,途中就可能溢出了,我们的数字就坏了,我们对坏了的数字取余肯定的不能得到正确的结果了。
从1到39的阶乘们和求和并且累加,累加的时候也要注意取余,因为有可能累加的过程中也会出现溢出,我们每加一次要保留正确的后九位。
sum+=z;
sum%=1000000000;
在每次累加阶乘之后,要把我们z还变回1,不然就会上一个阶乘的值又再来一遍
z=1;
第二种
第二种是我在题解里看见的,比我的要简单(我很笨)
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
long long int s=0,ij=1;
for(int i=1;i<=40;i++)
{
ij=ij*i%1000000000;
s+=ij;
}
s=s%1000000000;
printf("%lld",s);
return 0;
}
for(int i=1;i<=40;i++)
{
ij=ij*i%1000000000;
s+=ij;
}
s=s%1000000000;
我们知道n!=(n-1)!*n
这段就是这个意思
i=1时,ij=1*1 sum=1
i=2时,ij=1*1*2 sum=1+2
i=3时 ij=1*1*2*3 sum=1+2+6
......
这个比我想的那个简单,不过我想到了一个让人悲伤的事就是其实这种方法大一的时候老师讲过,救命!!!
今天的分享就到这里,拜拜!