您的位置:首页 > 其它

ZCMU—1375

2017-01-01 23:09 225 查看

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
这表明,5的倍数贡献了一个5,5^2的倍数又贡献了一个5...

比如: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:;
}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: