爱思创 181111 阶乘之乘 题解
题目大意
求出 \(1!*2!*3!*4!*……*n!\) 的末尾有几个零
小A:这跟题目有啥区别
铺垫知识
我们知道,\(n! = 1\times2\times3\times\dots\times n\),\((n - 1)! = 1\times2\times3\times\dots\times (n - 1)\)
小B: 那么我们可以推出 \(n! = n\times (n - 1)!\) 。
思路
先写一个大体模板
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= i; j ++)//1.求阶乘
//2.再乘上阶乘
}
//3.求末尾零的个数
时间复杂度:\(O(n^2)\)
\(n\le10^8\)
小A、小B: 不用想,肯定超时
回想铺垫知识
\(n! = n\times (n - 1)!\)
小A: 可以优化成
int s1;
for(int i = 1; i <= n; i ++)
{
s1 *= i;//1.求阶乘
//2.再乘上阶乘
}
//3.求末尾零的个数
时间复杂度:\(O(n)\)
时间够了,但是……
\(n\le10^8\)
小A: 换long long啊
小B: emmm,25的阶乘已经超过long long上限了,所以int换long long也没用
我们只能另找方案
正确思路
我们知道末尾零的个数只跟这些数中因数2和因数5有关,等于它们俩中的最小值
小B: 因数5总是比因数2少,所以我们只用求因数5的个数即可
小A: 那么每次求出当前的i的因数5的个数加在i的阶乘的因数5的个数中,再加到总数中就行了
所以完整代码是
#include<bits/stdc++.h>
using namespace std;
long long sum5/*答案*/, s5/*当前阶乘中因数5的个数*/;
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++)
{
int ii = i;
while(ii % 5 == 0)//求因数5的个数
{
s5 ++;//每次不清零,继承上一次的
ii /= 5;
}
sum5 += s5;
}
cout << sum5;
return 0;
}
小A、小B: AC啦~
作者:这是我第一次使用小A、小B两个角色,使我的题解更加生动有趣。有时他们有些搞笑,有时却能有很好的思路。希望加入这两个角色会是我的题解更好,更明了。
hello, I'm yuzihang, if you need to copy this, please quote this url: https://www.cnblogs.com/yuzihang/articles/16971392.html

浙公网安备 33010602011771号