数据范围较大,阶乘直接计算会溢出。所以不能直接计算阶乘再输出右侧第一个非零数字。
暴力算法:
可以把每次的结果保留后面 7 位不为 0 的数字。
注意:不能保留 1 位或者 2 位。
假设是20!
即 1 * 2 * 3 * 4 * ... * 20
这里面 2 * 5
有 0
,4 * 10
也有 0
, 可以想象在数非常大的时候末尾的 0 肯定不止一个两个
#include <cstdio>
using namespace std;
const int MOD = 1e6;
int n, res = 1 ;
int main(){
scanf("%d",&n);
for(int i = 1; i <= n; i++){
res *= i;
while(res % 10 == 0) res /= 10; //每次都去掉末尾的 0
res %= MOD; //保留 6 位数
//(我试过保留 7 位,8 位都溢出了QAQ ,但是仔细想象的确会溢出,,比如500 * 一个 8 为数明显会爆出int的范围)
//int 上限: 2147483647
}
printf("%d\n",res%10);
return 0;
}
“你好暴力!!”
当然这题也有其他解法
但是你要知道这个玩意n! = 2^x * 5^y * p = S
,那么问题转换成求(S/10^k)%10
#include<bits/stdc++.h>
using namespace std;
//n! = 2^x * 5^y * p = S
//即求 (S/10^k)%10 k = min(x,y)
int n,ans = 1,d2,d5;
//ans储存答案 d2表示n!中2^d2 d5表示n!中5^d5
int main()
{
cin>>n;
for(int i = 1; i <= n; i++){
int x = i;
while(x % 2 == 0) x /= 2, d2++;
while(x % 5 == 0) x /= 5, d5++;
ans = ans*x%10;
}
int k = min(d2,d5);
for(int i = 1; i <= d2 - k; i++) ans = ans*2%10;
for(int i = 1; i <= d5 - k; i++) ans = ans*2%10;
cout<<ans<<endl;
}