题解 P1134 【阶乘问题】

· · 题解

这题数据太水了 O(n)算法加上一个偌大的常数(div 与 mod很慢)都可以过 建议增强

正解是楼下曹彦晨大神讲的方法 但是讲的似乎并不清楚 于是鄙人再次阐述一遍

我们很容易发现,阶乘的结果会是一个偶数(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,w,i;
int a[4]={6,8,4,2};
int main()
{
    scanf("%d",&n);
    w=1;
    while (n>0)
    {
        for (i=1; i<=n%10; i++)
            if (i!=5) w=w*i%10;
        n=n/5;
        w=w*a[n%4]%10;
    }
    printf("%d",w);
    return 0;
}

吐槽一下,下面的朴素代码..我很多东西看不懂..似乎多弄了很多东西