给定p,求最小的n使得n!的末尾含有p个0
对于n!可对其分解质因数如下:
n!=1*2*3*...*n
=(1)*(2)*(3)*(2*2)*(5)*(2*3)*...
要末尾有0很明显要质因数中要有2和5
而2出现的频率显然比5高
所以5的个数即为阶乘末尾0的个数
至于求质因数中5的个数,以125为例:
对于125!,125/5=25,我们只关心其中含5的部分
即有125!=...*(1*5)...*(2*5)...*(3*5)...*(4*5)...*(5*5)......*(25*5) (此时未完全分解为质因数),这时得到25个5
再把其中与5相乘的1、2、3、4、5、。。。、25提取出来,即得到25!
对于25!,25/5=5,同样只关心其中含5的部分
25!=.....*(1*5)*...*(2*5)...*(3*5)...*(4*5)...*(5*5),这时得到5个5
然后再把与5相乘的1、2、3、4、5提取出来,得到5!
很明显5!中含有一个5,
于是我们可以得到125!含有25+5+1=31个5,而2的个数显然比5多,于是可以得出125!的末尾有31个0
这样就能得到任意n!的末尾有多少个0
而题目最多要求1e8个0,当n为400000016时末尾的0就已达到,而n至少为5时末尾才有0
所以对于每次给定的q,二分上下极限求0的个数是否等于q即可
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
long long cntzero(long long n)
{
long long cnt=0;
while(n)
{
cnt+=n/5;
n/=5;
}
return cnt;
}
int main()
{
//freopen("in","r",stdin);
long long t,q,l,r,m;
cin>>t;
for(long long i=1;i<=t;i++)
{
cin>>q;
r=400000016;
l=4;
while(l<=r)
{
m=(r-l)/2+l;
if(cntzero(m)>=q)
r=m-1;
else
l=m+1;
}
if(cntzero(l)==q)
cout<<"Case "<<i<<": "<<l<<endl;
else
cout<<"Case "<<i<<": impossible"<<endl;
}
return 0;
}