洛谷P1134 阶乘问题

时间:2021-07-16 15:19:59

题目描述

也许你早就知道阶乘的含义,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。

输出格式:

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

输入输出样例

输入样例#1:
12
输出样例#1:
6

一般的做法是约分乘数,统计约掉2和5的次数,相互抵消,最后计算多出来的2……

隔壁rlt这样做跑了1000ms

然而我暴力乘居然跑了700+ms

迷……

 /*by SilverN*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
long long n;
long long tmp;
int main(){
long long i;
scanf("%d",&n);
tmp=;
for(i=;i<=n;i++){
tmp=tmp*i;
while(tmp%==) tmp/=;
tmp%=10000000LL;//迷,%100的话会错
}
printf("%lld\n",tmp%);
return ;
}

暴力

又写了个高端一点的解法,500+ms

 /*by SilverN*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
int x[][];
int n;
int cnt=;
int main(){
int i,j;
for(i=;i<=;i++)
for(j=;j<=;j++)
x[i][j]=(i*j)%;
scanf("%d",&n);
int tmp=n;
while(tmp){cnt+=tmp/;tmp/=;}
int ans=;
for(i=;i<=n;i++){
tmp=i;
while(tmp%==)tmp/=;
while((tmp&)== && cnt){
--cnt;
tmp/=;
}
ans=x[ans][tmp%];
}
printf("%d\n",ans);
return ;
}