【十三届蓝桥杯真题】求阶乘 --- 数学解法思考与尝试

【十三届蓝桥杯真题】求阶乘 --- 数学解法思考与尝试,第1张

🚀写在前面 Hello大家好😋,我是秋刀鱼🐟,一只活跃于Java区与算法区的新人博主~ 欢迎大家加入高校算法学习社区: https://bbs.csdn.net/forums/Suanfa,社区里大佬云集,大家互相交流学习!
蓝桥杯比赛终于告一段落了,感谢这一路上付出的你🧡。


这道求阶乘题目是今天较难的一道题目,这里我给大家分享下我的解题思路,不代表一定正确!仅供参考😋。



🎉🎉期待你的支持与关注🎉🎉 🎉🎉主页:秋刀鱼与猫🎉🎉

🛸目录
    • 🚀写在前面
    • 🚀题目描述
    • 🚀解题思路(仅供参考)
    • 🚀代码(仅供参考)
    • 🧡写在最后


🚀题目描述

🚀解题思路(仅供参考)

题目给定K的最大值为 1 0 18 10^{18} 1018,显然暴力解法是无法AC的,此时就需要更换思路。


题目中所求的是一个数阶乘后0的数量,不妨想想什么样的情况下会产生0呢?只有乘法运算为:2*5 时才会产生一位的 0 ,其余乘法运算均不会产生0。


有了这个结论,不妨我们假设返回的结果为 M M M ,也就是说 M ! M! M! 后存在 k k k 个0。


为了找到式中有多少个 2*5,不妨我们将每一个数进行拆分为其因子,因为 2 因子出现的次数远大于 5 因子出现的次数,因此只需要找到 [ 1 , M ] [1,M] [1,M] 区间内的数中 5 因子的个数就是 k k k 的值。


如果直接遍历 5 的倍数 5,10,15,20,..., 进行寻找必定会超时,因为数据量实在是太大了,因此下面进行第二次探究。


这样思考:5能够提供 1 个5因子,25能够提供 2 个5因子,125 能提供 3 个5因子,…,那么现在给定一个值 M M M ,如何计算其 5因子的总数呢?先看看下面这张图:

对于所有能整除5的数来说:如果其存在5因子,则第一列的值存在;如果其存在25因子,则第二列的值存在;如果其存在125因子,则第三列的值存在,这样顺序推导下去:

那么对于 [ 1 , M ] [1,M] [1,M]区间内的所有值:值存在5因子的数量为: M / 5 M/5 M/5 ;值存在25因子的数量为: M / 25 M/25 M/25 ;值存在125的数量为: M / 125 M/125 M/125…,所有这些值的和,就是 5 因子的总数 K K K

因此推导出5因子总数K与结果值 M M M的关系为:

通过等比数列求和公式化简为: ( 1 − ( 1 / 5 ) n ) M = 4 K (1-(1/5)^n)M=4K (1(1/5)n)M=4K,所以当 n − > + I N F n->+INF n>+INF 时, M = 4 k M=4k M=4k


又因为 K K K的最大值为: 1 0 18 10^{18} 1018,因此 M M M的最大值为 4 ∗ 1 0 18 4*10^{18} 41018,所以 n n n的最大值也可以计算出来,这里假定为 30 30 30


现在输入一个数据 K K K后,根据公式 ( 1 − ( 1 / 5 ) n ) M = 4 K (1-(1/5)^n)M=4K (1(1/5)n)M=4K ,计算出不同的 n n n值对应的 4 K / ( 1 − ( 1 / 5 ) n ) 4K/(1-(1/5)^n) 4K/(1(1/5)n)的值放入数组 n u m s nums nums中,在以 n n n从小到大的顺序(保证 M M M值最小)判断 n u m s [ n ] nums[n] nums[n]的值是否符合要求(即: 5 n 5^n 5n是最大的小于等于 n u m s [ n ] nums[n] nums[n]的5的幂)。


如果判断是符合要求的数,因为 M M M的值要求:最小、 M > = n u m s [ n ] M>=nums[n] M>=nums[n] M % 5 = = 0 M \%5 ==0 M%5==0恒成立,因此计算出来的 n u m s [ n ] nums[n] nums[n]需要特殊处理,也就是找到第一个大于等于 n u m s [ n ] nums[n] nums[n]且取余5为0的值,就是 M M M


最后将M,K,n的值代入原式中判断等式是否成立,如果成立则等式输出M,否则输出-1


🚀代码(仅供参考)

因为蓝桥杯系统该题的调试还没有上线,因此该代码仅供参考!

import java.util.Scanner;

public class Main {
    static boolean judge(long k, long M, int n) {
        long m = 5;
        while (n >= 1) {
            k -= (M / m);
            --n;
            m *= 5;
        }
        return k == 0;
    }
    static double[] nums = new double[30];
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        long k = cin.nextLong();
        for (int i = 1; i < 30; ++i) {
            nums[i] = (4 * k) / (1 - Math.pow(0.2, i * 1.0));
        }
        for (int i = 1; i < 30; ++i) {
            double cur = Math.pow(5, i);
            double tCur = Math.pow(5, i + 1);
            if (nums[i] >= cur && nums[i]*1.0 < tCur) {
                long lI = (long) (nums[i]);
                int mod = (int) (lI % 5);
                if (lI != nums[i]) {
                    lI += 5;
                }
                lI -= mod;
                if (judge(k, lI, i)) {
                    System.out.println(lI);
                    return;
                }
            }
        }
        System.out.println(-1);
    }
}

🧡写在最后

比赛虽然告一段落,但未来的路还有很长,我们应当砥砺前行、共同进步,为美好的明天而战🤗!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/606968.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-14
下一篇 2022-04-14

发表评论

登录后才能评论

评论列表(0条)

保存