题目大意:
计算N!的最右边的非零位的值。
1<=N<=50,000,000
题解:
N!(N≠1)的末尾只会是2,4,6,8(题目不存在0)。
因为
=表示他们的最右边非零位相同
2 * 6 = 12 = 2 , 4 * 6 = 24 = 4,
6 * 6 = 36 = 6 , 8 * 6 = 48 = 8,
即[2,4,6,8]任意一个*6都为自身
因为末尾数字只受末尾数字影响,即 i*6=i*16=i*106
然后因为4 * 2 8==4 2 * 5
所以我们将所有的2*5中的5,换成*8
因为*8有规律所以可以直接做
某dalao的题解(详):
设a==b等价于a、b去掉后缀0的尾数相等:
1.若k为4的倍数,则k5==k8
why?
设k=4n,则k5==n20,k8==n32
而20==32,于是n20==n32,证毕
2.阶乘中4的倍数不少于5的倍数
why?
对于每个a=5n<k,都必然存在b=4n<k(n为任意正整数),证毕
3.若输入大于1,则结果必为2,4,6,8之一
why?
设输入为k,则结果为k!=123...k,那么只要k>1,结果的因子中就会包含2
所以结果为偶数,而结果根据定义是一个非0值,那就只有2,4,6,8了,证毕
4.若a为偶数,则a*6==a
why?
设a=2n,则a6==n12==n10+n2==n*2==a,证毕
于是乎,设输入n,则在[1,n]中的5的倍数15,25,35...与对应的4的倍数14,24,34...相乘为(154)(258)(3512)...==(123...)(54)(58)(512)...==(123...)(84)(88)(812)*...
再把4的倍数拿出来,就相当于51015...==(123...)(888...)
而10!不含5的倍数的部分12346789==6,20!不含5的倍数的部分611121314161718*19==6,同理整十数不含5的倍数的阶乘都==6
因为n中有n/5个5的倍数,所以n!==(n-n%10)!+(n%10)!==6(123...n/5)(888...)(n%10(去掉5))!==(n/5)!(8^n/5)*(n%10(去掉5))!
用同样的方法再算(n/5)!,8^k的尾数是循环的,只要算8^(k%4),再暴力乘出(n%10(去掉5)),答案就出来了
代码:
#include<bits/stdc++.h>
using namespace std;
int a[4],n;
int main()
{
scanf("%d",&n);
if (n==1) {printf("%d\n",1); return 0;};
a[0]=6; a[1]=8;
a[2]=4; a[3]=2;
int ans=1;
while (n)
{
for (int i=1; i<=n%10; i++)
if (i!=5) ans=ans*i%10;
n/=5;
ans=ans*a[n%4]%10;
}
printf("%d\n",ans);
}