c语言【阶乘求和】2023蓝桥杯3500(阶乘)

文章介绍了计算大数阶乘时遇到溢出问题的解决方案,提出两种方法:一种是通过取余操作确保每个乘法步骤后保留后九位,另一种是利用数学性质简化为连续乘积并取余。作者分享了C语言代码实现和注意事项。
摘要由CSDN通过智能技术生成

你好\(@^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

......

这个比我想的那个简单,不过我想到了一个让人悲伤的事就是其实这种方法大一的时候老师讲过,救命!!!

今天的分享就到这里,拜拜!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潮倾的敲代码之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值