原题目为leetcode上面的题和我学校oj上面的题目
若要先明白xujcoj--How many zero-2怎么写,首先先要明白leetcode阶乘尾数这道题,不妨看看下面两位大佬的分享,先看知乎的思路后看力扣的代码
好了,我们明白力扣上那道题目后,接下来就是xujcoj上xujcoj--How many zero-2这道题目了
这一切有一个前提条件,那就是比如3!×4!×5!×6!= 6 * 24 *120 * 720 = 12441600,在计算中末尾0的个数的时候,
6*24*12*72并不会产生新的0,只需要计算每个阶乘原有的0相加即可,因为偶数乘以奇数全部都是偶数阶乘出来的数字全部都是偶数,里面不包含5
我就拿一个例子举例吧;比如n = 5,m = 21;即计算 5!×6!×…×21!中0的个数,先算1!×2!×…×21!中0的个数,减去1!×2!×…×4!中0的个数。*1!×2!×…×21!中,把数字分为5个为一组,即1!×2!×…×4!,5!…9!,10!…14!,15!…19!,每一组数字0的数目不同,但在同一组内是相同的
即5!…9!各有1个0,即1 + 1 + 1 + 1 + 1(共5个),10!…14!各有2个0,即2 + 2 + 2 + 2 + 2(共5个),15!…19!各有3个0,即3 + 3 + 3 + 3 + 3(共5个),
设i = 5,k = m / i = 21 / 5 = 4,这个k=4代表我已经有4组数字,每一组5个,组内的每个数字末尾0的个数相同,要相加了,这个例子就是0+0+0+0+0+1 + 1 + 1 + 1 + 1+2 + 2 + 2 + 2 + 2+3 + 3 + 3 + 3 + 3,从1加到3,即从1算到k - 1即k * (k - 1) / 2 * i,这个通项公式是高中数列的问题,我就不多赘述。
再加上20!…21!中各有4个0(共有1 + m % i = 1 + 21 % 5 = 2个),即k * (1 + m % i)。
以此类推,i = 5 * 5… 计算总和即可算出1!×2!×…×m!中0的个数。为什么k * (1 + m % i)里面要加1呢,是因为原本21%5等于1,只把21算上了,没算20,而20!和21!末尾0的个数又是相同的,在一组内。
代码如下:
#include<iostream>
using namespace std;
typedef long long ll;
ll n, m, r = 0, l = 0;
int main()
{
cin >> n >> m;
//i会递增,i会等于5,25,125,625....,当n=0,m=49的时候,i=25的时候就相当于0的总数要加上0*25+1*25个0
for (ll i = 5; i <= m; i *= 5)
{
ll k = m / i;
r += k * (k - 1) / 2 * i + (1 + m % i) * k;
}
n--;
for (ll i = 5; i <= n; i *= 5)
{
ll k = n / i;
l += k * (k - 1) / 2 * i + (1 + n % i) * k;
}
//先算1!×2!×…×21!中0的个数,减去1!×2!×…×4!中0的个数
cout << r - l;
}