传送门
题目看上去非常不可做。
考虑缩小答案规模。
首先将25!拆分:
25!=(1∗2∗3∗4∗5)∗(6∗7∗8∗9∗10)∗(11∗12∗13∗14∗15)∗(16∗17∗18∗19∗20)∗(21∗22∗23∗24∗25)
将每一组末尾的模5为0的数除以5,并且和前面的2消掉,得到
答案=(1∗1∗3∗4)∗(3∗7∗8∗9)∗(11∗6∗13∗14)∗(8∗17∗18∗19)∗(21∗11∗13∗14)∗(1∗2∗3∗4∗5)
前面每一坨东西末尾都是2。
于是我们没进行依次这样的操作,规模变为原来的1/5
多迭代几次就行了。
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100100
using namespace std;
char s[505];
int a[505];
int biao[25]={
1,1,2,6,4,
2,2,4,2,8,
8,8,6,8,2,
8,8,6,8,2,
4,4,8,4,6
};
int mi[4]={6,2,4,8};
int solve(int *a){
int m,x;
m=a[2]*10+a[1];
if (a[0]<=2&&m<25) return biao[m];
m=0;
int b[505];
memset(b,0,sizeof(b));
for (int i=a[0];i>=1;i--){
m=m*10+a[i];
b[i]=m/25;
m%=25;
}
b[0]=a[0];
while (b[0]&&!b[b[0]]) b[0]--;
x=b[1]+b[2]*10;
for (int i=1;i<=a[0];i++) b[i]*=5;
for (int i=1;i<=a[0];i++){
b[i+1]+=b[i]/10;
b[i]%=10;
}
if (b[b[0]+1]) b[0]++;
return solve(b)*biao[m]*mi[x%4]%10;
}
int main(){
while (scanf("%s",s+1)!=EOF){
memset(a,0,sizeof(a));
a[0]=strlen(s+1);
for (int i=1;i<=a[0];i++) a[i]=s[i]-'0';
for (int i=1,j=a[0];i<j;i++,j--)
swap(a[i],a[j]);
printf("%d\n",solve(a));
}
}