题解 P1134 【阶乘问题】
a526955194 · · 题解
这题数据太水了 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;
}
吐槽一下,下面的朴素代码..我很多东西看不懂..似乎多弄了很多东西