1375: 阶乘的零
Time Limit: 1 Sec Memory Limit: 128 MB[ Submit][ Status][ Web Board]
Description
定义f(n)为n!的末尾零的个数,例如f(4)=0,f(5)=1。你的任务是对于一个给定的的值x找出最小的n满足f(n)=x。
Input
多组测试数据,每组测试数据包含一个正整数x(1<=x<=10^8)。
Output
对于每组测试数据输出对应的n,若没有n满足则输出“No solution”。
Sample Input
2
Sample Output
10
HINT
water problem!
【分析】
首先...我们要会算n!有几个0,显然有几个0取决于n!这个数中因子2的个数和因子5的个数,显然2的个数远大于5,所以只要考虑因子5的个数就可以了~当然不能用n的算法...需要log5(n)的速度...
对N进行质因数分解 N=2^x * 3^y * 5^z...,由于10 = 2*5,所以末尾0的个数只和x与z有关,每一对2和5相乘可以得到一个10,于是末尾0的个数=min(x,z)。在实际中x是远远大于z的,所以我们只要求出z的值即可。
根据公式
z = N/5 + N/5^2 + N/5^3+...+N/5^k
根据公式
z = N/5 + N/5^2 + N/5^3+...+N/5^k
这表明,5的倍数贡献了一个5,5^2的倍数又贡献了一个5...
比如:25其实是贡献了2个5,但是在N/5中已经贡献了一个,所以在N/5^2中再贡献一个;同样,125在N/5中贡献一个,在N/5^2中贡献一个,在N/5^3中再贡献一个,一共是3个。
比如:25其实是贡献了2个5,但是在N/5中已经贡献了一个,所以在N/5^2中再贡献一个;同样,125在N/5中贡献一个,在N/5^2中贡献一个,在N/5^3中再贡献一个,一共是3个。
知道这点之后就容易了,这道题显然是有数学公式可以直接求答案的...但是因为我比较懒所以写了个二分直接查答案了...因为上面这个算n!末尾0个数的速度太快了,加上二分基本上也属于常数算法...所以....嗯直接搜吧!手动给一个极大的区间然后搜就好了
【代码】
#include <stdio.h>
long long find(long long x)
{
long long ans=0;
while (x)
{
ans+=x/5;
x/=5;
}
return ans;
}
int main()
{
long long n;
while (~scanf("%lld",&n))
{
long long left=5;
long long right=1000000000000;
while (left<right)
{
long long mid=(left+right)/2;
long long m=find(mid);
if (m==n)
{
while (mid%5) mid--;
printf("%lld\n",mid);
goto out;
}
if (m>n) right=mid-1;else left=mid+1;
}
printf("No solution\n");
out:;
}
}