阶乘
n的阶乘定义为n!=123……n 如3!=6 n!通常最后会有很多0,如5!=120 最后有一个0,现在统计n!去除末尾的0后,最后k位是多少
输入格式:
第一行包括两个数n,k
输出格式:
如果n!不止k位,则输出最后k位,如果不足k位,则将剩下的全部输出
7!为5040,去除末尾的0为504,最后两位为04 100%满足1< =n< =20 1< =k< =9
样例输入
7 2
样例输出
04
问题链接:JSK-217 阶乘
问题描述:(略)
问题分析:
阶乘计算会越算越大,然而只需要计算最后k<=9位就好办了,使用模除可以取出最后若干位来。
需要分析一下,末尾的0是怎么来的。一般而言,有两种产生末尾0的原因:一是乘以末尾为0的数,即10的倍数的数;二是含有因子2的数与含有因子5的数的乘积(10=2*5)得到的,而含有因子2的数远多余含有5因子数。
计算过程中,如果仅仅取最右边k位持续计算则会造成有效数字的丢失,所以先多取一些位进行计算。最后再用模除取出最后k位。
程序说明:
程序中,输出k位前置为0的数的做法略微与众不同,值得效仿。用循环处理来实现高位补0那是浮云。
参考链接:(略)
题记:格式字符串也是可以在程序中算出来的。
AC的C语言程序如下:
/* JSK-217 阶乘 */
#include <stdio.h>
typedef long long LL;
#define BASE 10
#define MOD 1000000000000000LL
int main(void)
{
int n, k, i;
LL mod, ans;
scanf("%d%d", &n, &k);
mod = 1;
for(i = 1; i <= k; i++)
mod *= BASE;
ans = 1;
for(i = 2; i <= n; i++) {
if(i % BASE == 0)
continue;
ans *= i;
while(ans % BASE == 0)
ans /= BASE;
ans %= MOD;
}
and %= mod;
// 输出结果
char fmt[10];
sprintf(fmt, "%%0%dlld\n", k);
printf(fmt, ans);
return 0;
}