初学acmer--读《算法竞赛入门经典》笔记(二) p25-27

例题:阶乘之和      (p25-27)

题目:输入n,计算s=1!+2!+3!+...+n!的末六位(不含前导零)。n<=10^6

样例输入:

10

样例输出

37913

1.计算某表达式的末六位    可以转化为对1000000取余

ps:要计算只包含加减、乘法的整数表达式除以正整数n的余数,但是在过程中结果可能会溢出,可以在每一步计算之后对n取余,结果不变

先贴代码:

#include
#include
int main() 
{
	const int MOD=1000000;
	int n,s=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int factorial=1;
		for(int j=1;j<=i;j++)
		{
			factorial=(factorial*j%MOD);
		}
		s=(s+factorial)%MOD;
	}
     printf("%d\n",s);
     printf("Time used:%.2f\n",(double)clock()/CLOCKS_PER_SEC);
     return 0;
}
几点说明:

① 阴影处使用了time.h和clock()函数获得程序运行时间。常数CLOCKS_PER_SEC和操作系统有关,但不要直接使用clock()的返回值,而应总是除以CLOCKS_PER_SEC来得到以“秒”为单位的数值
② 以上获取程序运行时间的方法,其中键盘输入的时间也被计算在内,是从程序启动之后就开始计时了,所以可以采取一种称为“管道”的小技巧

在Windows命令行下(win+R后,输入cmd,回车),执行echo 20|abc(abc指代码生成的程序的名称),此后,操作系统会自动把20输入(??:在自己电脑上并未操作成功

③多次试验发现从输入40往后,得到的答案始终不再变化,究其原因,发现25!的末尾有六个零,所以n!(n>=25)对1000000求余结果都是零

所以可以在程序中加一句“if(n>25) n=25;”来优化程序的效率

ps:本题中n的范围是n<=10^6,一一枚举是不可能的,从中可以发现,当你发现范围太大,一是可能存在规律循环,二是可能过了一个临界后,不再变化,所以都可以多多试验,寻求规律

贴上最终代码:

#include
int main() 
{
	const int MOD=1000000;
	int n,s=0;
	scanf("%d",&n);
	if(n>=25)
	n=25;
	for(int i=1;i<=n;i++)
	{
		int factorial=1;
		for(int j=1;j<=i;j++)
		{
			factorial=(factorial*j%MOD);
		}
		s=(s+factorial)%MOD;
	}
     printf("%d\n",s);
     return 0;
}


你可能感兴趣的:(acm)