【USACO习题】阶乘问题

本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P1134


 

刚开始做的时候,是这样想的,只有n个数的最后一位才会对答案造成影响,所以只管最后一位就好,但是还要把某位多余的0除掉。结果只对了两个点,我们只保留最后一位导致运算出现了误差,比如n=15时就会出错,解决办法是每次适当多保留几位,但比较糊弄。。。

还有一种办法是求出2和5的个数,因为2的个数一定不少于5的个数,且一对2和5相乘会在末尾产生一个0,所以用2的个数减5的个数,剩下的就是实际会对答案造成影响的2的个数。

另外,有一种看起来很高端的做法,可以证明每次乘8或乘5对末位的影响是一样的,所以可以将乘5换成乘8,而乘8每4次末位一循环。这样做,实际上每次递归求解(n/5)!的末位,再与之前的相乘,也可以通过迭代实现。

 1 #include <cstdio>
 2 
 3 const int a[4] = {6, 8, 4, 2};
 4 
 5 int main() {
 6     int n, ans = 1;
 7     scanf("%d", &n);
 8     while (n > 0) {
 9         for (int i = 1; i <= n % 10; ++i)
10             if (i != 5) ans = ans * i % 10;
11         n /= 5;
12         ans = ans * a[n % 4] % 10;
13     }
14     printf("%d", ans);
15     return 0;
16 }
AC代码

 

posted @ 2018-10-21 23:17  Mr^Kevin  阅读(150)  评论(0编辑  收藏  举报