阶乘求和的n种境界

题目:输入n,计算s=1!+2!+3!+...+n!的末六位

思路;

我们知道n的阶乘的公式: n =   n ∗ ( n − 1)!

1,第一种境界

//想要求阶乘,及5!=1*2*3*4*5

由此很容易想到使用循环

即有了第一种境界

#define   _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	//使用循环且每次轮回加1
	//至少需要俩个未知数
	int n = 0;
	int s = 0;
	scanf("%d", &n);
	for (int i= 1; i<=n; i++)
	{
		int h = 1;
		for (int j = 1; j <= i; j++)
		{
			h = j * h;
		

		}
		s = s + h;
	}
	printf("%d", s);

	return  0;
}

如果这一段代码看不懂的话可以简写成这一种伪代码

for(int j=1;j,=n;j++);
s=s+i!

即其中嵌套的for循环为阶乘

但为社么如此好的方法被定义为第一中境界呢?

不妨输入100

来看一下运行结果

直觉告诉我们,乘法又溢出了

不论乘法溢出的话,再次我们使用时间计算来看一下运行时间

不论答案正确与否,这消耗的时间也算很久了,有没有更好更便捷的方式呢?

tip;使用time.h和clock()函数可以获得程序运行时间。常数CLOCKS_PER_SEC和操作系统相关。请不要使用clock()的返回值,而应总是除于CLOCKS_PER_SEC。

2,第二种境界

还有一种并不简单但是比较新奇的方式,当我们考虑到了递归思想后

即可把复杂的问题化为简单的问题

写出来求阶乘代码即为

#include <stdio.h>
int Fact(int n)
{
 if(n==0)
 return 1;
 else
 return n*Fact(n-1);
}
int main()
{
 int n = 0;
 scanf("%d", &n);
 int ret = Fact(n);
 printf("%d\n", ret);
 return 0;
}

再创立一个新的变量令他们相加即写出了完整的代码

#define   _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int Fact(int n)
{
	if (n == 0)
		return 1;
	else
		return n * Fact(n - 1);
}
int main()
{
	int ret = 0;
	int s = 0;
	int n = 0;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		ret = Fact(i);
		s = s + ret;
	}
	
	printf("%d\n", s);
	return 0;
}

不用多想,这样子的代码乘法也必然会溢出,虽然思路很新奇那么有没有不会溢出的方案呢?

3,第三种境界

#define   _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>
int main()
{
	const int mod = 1000000;
	int n, s = 0;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		int h = 1;
		for (int j = 1; j <= i; j++)
			h = j * h%1000000;
		    s = (s + h)%1000000;
	}

	printf("%d", s);
	printf("time used=%.2f\n", (double)clock() / CLOCKS_PER_SEC);
	return 0;
}

这种方法求的值一定是正确答案吗?

由图可见不仅仅时间变长了,如果我们输入40那么值为多少呢?

答案始终不变,是真理还是巧合?不妨设想一下,25!,末尾有六个0,所以从第25项开始,后面的所有相都不会影响和的末六位数字,故此不用担心,

因此,使用这种解法,不用考虑乘法溢出等等。

  • 14
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值