P1134 [USACO3.2]阶乘问题 题解

题目传送门

题目描述

也许你早就知道阶乘的含义,N阶乘是由1到N相乘而产生,如:

12! = 1 * 2 * 3 * 4  *  5  *  6  *  7  * 8 *  9  *  10  *  11 * 12 = 479,001,600

12的阶乘最右边的非零位为6。

写一个程序,计算N(1 <= N <= 50,000,000)阶乘的最右边的非零位的值。

注意:10,000,000!有2499999个零。

 输入格式

仅一行包含一个正整数N。

输出格式

一个整数,表示最右边的非零位的值。

 样例 #1

样例输入 #1


12

样例输出 #1


6

提示

USACO Training Section 3.2

题解:

如果打暴力,可以骗到14分。

我们可以用一个小小的技巧:边乘边模。

如果每次 mod 10,会造成误差.因为当相乘后得到的是10的倍数时,mod 10 会变成0.所以每次大概mod 1000000.最后输出ans%10。

#include<bits/stdc++.h>
using namespace std;
int n;
long long sum=1;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++){
        sum*=i;
        while(sum%10==0)sum/=10;
        sum%=100000000;
    }
    cout<<sum%10;
    return 0;
}
  • 数学方法:

  • 第一种分析10怎么出现.发现如果两个数的因数中分别有2,5.那么相乘末尾一定有0.于是统计1~N中每个数的因数中2和5的个数.用2的个数减去5的个数(2的个数一定比5的个数多).剩下的是会对答案(即末尾的数)造成影响.之后大胆mod 10 就行了.

  • 第二种应该是正解.分析:N!的末尾只会是2,4,6,8(在此题中没有0).又[2,4,6,8]中任意一个数乘6,末尾仍是本身.2 * 6 = 12,末尾为2, 4 * 6 =24,末尾为4, 6 * 6=36,末尾为6,8 * 6 =48,末尾为8.又末尾数字只受末尾数字影响,如4. 4 * 6得到的末尾数字与4 * 16的末尾数字一样.又4 * 10=40,末尾数字为4(此题不要末尾0).则4 * 2 *8==4 * 2 *5(意思是得到的末尾数字是一样的).故所有乘5的时候都可以换为乘8.又多次乘8末尾是有规律的.找出规律即可.

 代码:

#include<bits/stdc++.h>
using namespace std;
int n,ans=1;
int a[4]= {6,8,4,2};
int main() 
{
    cin>>n;
    while (n>0) {
        for (int i=1; i<=n%10;++i)
            if(i!=5)ans=ans*i%10;
        n/=5;
        ans=ans*a[n%4]%10;
    }
    cout<<ans;
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值