数论 + 二分 (阶乘后缀0的个数) - Trailing Zeroes (III) - LightOJ 1138

数论 + 二分 (阶乘后缀0的个数) - Trailing Zeroes (III) - LightOJ 1138

题意:

n 的 阶 乘 尾 部 有 q 个 连 续 的 0 , 现 在 给 你 q , 请 你 算 出 满 足 条 件 的 n , 如 果 有 多 个 n 满 足 条 件 , 输 出 最 小 的 那 个 即 可 。 n的阶乘尾部有q个连续的0,现在给你q,请你算出满足条件的n,如果有多个n满足条件,输出最小的那个即可。 nq0qnn

Input

输入一个T(T ≤ 10000),表示样例数量。

每个样例输入一个q。(1 ≤ q ≤ 100,000,000)

Output

对于每个样例,输出满足条件的最小的n,如果没有满足条件的则输出"impossible"。

Sample Input

3
1
2
5

Sample Output

Case 1: 5
Case 2: 10
Case 3: impossible

T i m e   l i m i t : 2000 m s , M e m o r y   l i m i t : 32768 k B Time\ limit:2000 ms,Memory \ limit:32768 kB Time limit:2000ms,Memory limit:32768kB


分析:

每 个 数 的 后 缀 0 的 个 数 , 取 决 于 其 质 因 子 2 和 5 的 指 数 。 每个数的后缀0的个数,取决于其质因子2和5的指数。 025

阶 乘 后 缀 0 的 个 数 , 取 决 于 质 因 子 5 的 指 数 , 因 为 5 的 指 数 恒 大 于 等 于 2 的 指 数 。 阶乘后缀0的个数,取决于质因子5的指数,因为5的指数恒大于等于2的指数。 0552

因 为 答 案 是 满 足 单 调 性 的 , 求 最 小 值 , 我 们 可 以 直 接 二 分 答 案 。 因为答案是满足单调性的,求最小值,我们可以直接二分答案。

对 每 个 二 分 的 答 案 m i d , 我 们 判 断 m i d 的 阶 乘 , 质 因 子 5 的 指 数 , c a l ( m i d ) 是 否 大 于 等 于 q 。 对每个二分的答案mid,我们判断mid的阶乘,质因子5的指数,cal(mid)是否大于等于q。 midmid5,cal(mid)q

二 分 得 到 满 足 m i d ! 的 因 子 5 的 指 数 , c a l ( m i d ) ≥ q 的 最 小 的 m i d , 二分得到满足mid!的因子5的指数,cal(mid)≥q的最小的mid, mid!5,cal(mid)qmid

然 后 我 们 看 c a l ( m i d ) = q 是 否 成 立 即 可 。 然后我们看cal(mid)=q是否成立即可。 cal(mid)=q

注意:

二 分 的 边 界 l = 5 , 考 虑 右 边 界 r : 二分的边界l=5,考虑右边界r: l=5r

至 多 有 1 0 9 个 后 缀 0 , 即 因 子 5 的 指 数 为 1 0 9 , 至多有10^9个后缀0,即因子5的指数为10^9, 10905109

每 间 隔 10 , 至 少 会 出 现 两 个 数 的 因 子 中 包 含 5 1 , 每间隔10,至少会出现两个数的因子中包含5^1, 1051

则 r 10 × 2 = 1 0 9 , 可 得 r = 5 × 1 0 9 , 可 粗 略 估 计 出 右 边 界 不 超 过 5 × 1 0 9 。 则\frac{r}{10}×2=10^9,可得r=5×10^9,可粗略估计出右边界不超过5×10^9。 10r×2=109r=5×1095×109

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>

#define ll long long

using namespace std;

ll cal(ll n)
{
    ll s=0;
    for(ll i=n;i;i/=5) s+=i/5;
    return s;
}

int main()
{
    int T; cin>>T;
    for(int t=1;t<=T;t++)
    {
        int q; scanf("%d",&q);
        ll l=5, r=1e10;
        while(l<r)
        {
            ll mid=l+r>>1;
            if(cal(mid)>=q) r=mid;
            else l=mid+1;
        }
        
        printf("Case %d: ",t);
        if(cal(l)!=q) puts("impossible");
        else printf("%lld\n",l);
    }
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值