题目:输入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项开始,后面的所有相都不会影响和的末六位数字,故此不用担心,
因此,使用这种解法,不用考虑乘法溢出等等。