算法训练 P0505

P0505

n!=1234.......(n-1)n, n!末尾的0的是由因子2和5造成的。
可以这么想,先将1到n每个数做关于2和5的因数分解,其实想法十分简单就是在计算阶乘时将所有因数2和5都不乘进去。而是用a,b分别记录2的个数和5的个数。
ans记录的是n!末尾非零的数字,初始化ans=1。

#include<iostream>
#include<math.h>
using namespace std;
int a=0, b=0;
int main(){
    long long int n, ans=1, t;
    cin>>n;
    for(int i=1; i<=n; i++){
        t=i;
        while(t%2==0){ //将t中的2全部剔除掉,并把含有2因子的个数加到b上
            a++;
            t/=2;
        }
        while(t%5==0){ //将t中的5全部剔除掉,并把含有5因子的个数加到b上
            b++;
            t/=5;
        }
        if(t!=0)
            ans*=t;
        ans=ans%10; //保证ans记录的是一个个位数,是n!的最后一个非零的数
    }
    if(a>b){ //2的个数比5多
        switch((a-b)%4){ //只需要考虑比5多出来的2就好了,而2,4,8,16,32,64,......发现其末位数字具有周期性
            case 0: ans=ans*6; break;
            case 1: ans=ans*2; break;
            case 2: ans=ans*4; break;
            case 3: ans=ans*8; break;
            default: break;
        }
    }else if(b>a) //处理多出来5,不管多出来多少个5,它们的乘积个位数都是5.
        ans*=5;
    ans=ans%10;
    cout<<ans<<endl;
    return 0;
} 

转载于:https://www.cnblogs.com/A-Little-Nut/p/10360413.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值