您的位置:首页 > 其它

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

2017-07-25 15:43 183 查看
例题:阶乘之和      (p25-27)

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

样例输入:

10

样例输出

37913

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

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

先贴代码:

#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 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<stdio.h>
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: