Factorials(数学)

Factorials

The factorial of an integer N, written N!, is the product of all the integers from 1 through N inclusive. The factorial quickly becomes very large: 13! is too large to store in a 32-bit integer on most computers, and 70! is too large for most floating-point variables. Your task is to find the rightmost non-zero digit of n!. For example, 5! = 1 * 2 * 3 * 4 * 5 = 120, so the rightmost non-zero digit of 5! is 2. Likewise, 7! = 1 * 2 * 3 * 4 * 5 * 6 * 7 = 5040, so the rightmost non-zero digit of 7! is 4.

PROGRAM NAME: fact4

INPUT FORMAT

A single positive integer N no larger than 4,220.

SAMPLE INPUT (file fact4.in)

7

OUTPUT FORMAT

A single line containing but a single digit: the right most non-zero digit of N! .

SAMPLE OUTPUT (file fact4.out)

4

 

       题意:

       给出一个数 N (1 ~ 4220),求出 N!,输出最右第一个非零的数。

 

       思路:

       数学。我的做法是直接保存后面的 K 位数,一旦有 0 就不断删除 0,最后输出 % 10 的答案即可。

       官方解答是找出 2 和 5 的对数,因为 2 X 5 或者 5 X 2 是使末尾变为 0 的关键,所以找出 1 ~ N 中因子 2 的个数和因子 5 的个数,排除最大对数的 2 和 5 之后,剩下的数相乘就不会产生进位了,那么直接保存最后一位相乘的结果就好。因为 2 的个数肯定要比 5 的个数多,所以 5 的个数即为最大的对数,所以最后还要乘上剩下未匹配的 2,即乘上 (n5 - n2)个 2 后才是结果。

 

     AC1:

/*
TASK:fact4
LANG:C++
ID:sum-g1
*/

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

int main() {

    freopen("fact4.in", "r", stdin);
    freopen("fact4.out", "w", stdout);

    int n;
    scanf("%d", &n);

    ll last = 1;
    for (int i = 1; i <= n; ++i) {
        last *= i;
        while (!(last % 10)) last /= 10;
        last %= 100000000000;
    }

    printf("%lld\n", last % 10);

    return 0;
}

 

     AC2:

/*
TASK:fact4
LANG:C++
ID:sum-g1
*/

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int main() {

    freopen("fact4.in", "r", stdin);
    freopen("fact4.out", "w", stdout);

    int n;
    scanf("%d", &n);

    int n2 = 0, n5 = 0, last = 1;
    for (int i = 1; i <= n; ++i) {
        int j = i;
        while (!(j % 2)) {
            ++n2;
            j /= 2;
        }

        while (!(j % 5)) {
            ++n5;
            j /= 5;
        }

        last = (last * j) % 10;
    }

    for (int i = 1; i <= n2 - n5; ++i)
        last = (last * 2) % 10;

    printf("%d\n", last);

    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值