洛谷 数论T2 1134

来源:互联网 发布:四维设计软件 编辑:程序博客网 时间:2024/06/06 02:40

题目描述:

       也许你早就知道阶乘的含义,N阶乘是由1到N相乘而产生,如:12! = 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x 11 x 12 = 479,001,600,12的阶乘最右边的非零位为6。写一个程序,计算N(1<=N<=50,000,000)阶乘的最右边的非零位的值。注意:10,000,000!有2499999个零。


输入格式:
       仅一行包含一个正整数N。 

输出格式:

        单独一行包含一个整数表示最右边的非零位的值。


输入样例:

        12

输出样例:

         6


解题思路(从洛谷题解中转载):

     我们很容易发现,阶乘的结果会是一个偶数(0!与1!除外,我也非常惊讶为什么数据里没有0!),即数的末尾只可能是(2,4,6,8)(屏蔽0),经过观察之后,我们可以发现这样一个规律:(2,4,6,8)任意一个数乘6之后,其最后一位是不会变的,下面我们拿4来举例,ans表示最后一位:ans(4*10)=ans(4*6)=ans(4*16) (最后一位的结果只与两个数的末位有关)可以推得:ans(4*2*5)=ans(4*2*8)这是一个重要的结论,当乘5的时候,我们可以用8来替代,这样就不会出现0了可是还有一个问题:我们应该怎样替代呢?如果仅仅是这样的话复杂度还是O(n)
答案是每做一次 我们可以将n/5,得到的结果是5的乘的次数,也就是我们需要代替成乘8的次数我们发现,多次乘8肯定是要出事的,经过观察发现,多次乘8的末尾变化是有规律的:8,4,2,6 四次一循环这样的话就很简单了:


代码:

#include<cstdio>
using namespace std;
int n,i,t;
int a[4]={6,8,4,2};
int main()
{
    scanf("%d",&n);
    t=1;
    while(n>0)
    {
       for(i=1;i<=n%10;i++)
         if(i!=5) t=t*i%10;
       n=n/5;
       t=t*a[n%4]%10;    
    }
    printf("%d",t);
    return 0;
}

0 0