蓝桥杯13届真题-求阶乘(算数基本定理、二分)

前言

本题为蓝桥杯第13届JavaB组省赛真题,分值为15分。

标签:算数基本定理、二分、枚举

蓝桥杯第13届JavaB组省赛真题及题解可见个人博客:第十三届蓝桥杯省赛JavaB组真题(Java题解解析)

本题在线OJ平台:蓝桥杯官网在线OJ-求阶乘

题目

image-20230311185331445

image-20230311185341257

题解

根据算数基本定理可以将一个数分解成若干个数的乘积。

n! = N = P1a1 P2a2 P3a3 * … Pnan,本题中需要统计的是后缀连续0的个数,那么也就是目标n!中对于10的阶乘个数,又10 = 2 * 5,想要求得目标10,那么我们就需要去匹配多对2与5,此时即为找到min(质因子2的个数,质因子5的个数),又质因子2的个数是大于5的个数,所以我们可以直接去求质因子为5的个数 == k。

对于一个数n,求得该n!中质因子为5的个数,我们只需要去对n进行不断相除即可求得。

扫描二维码关注公众号,回复: 15524832 查看本文章
//计算n中有多少个5
public static long check(int num) {
    
    
    long res = 0L;
    while (num > 0) {
    
    
        res += num / 5;
        num /= 5;
    }
    return res;
}

解法1:枚举1-108,每一个数表示阶乘,来去求得该阶乘的值是否是>=k,找到第一个也就是最小的n即为答案。

  • 这里枚举到108目的就是由于时间复杂度为O(n.logn),而运算次数为1亿次差不多就是1秒,所以这里取相对在临界位置的值即可。

解法2:由于去check 1-108得到的结果是递增的,那么这个枚举的过程可以修改为二分来进行搜索,此时复杂度可以直接优化为O(logn.logn),直接ac。


解法1:算数基本定理+枚举(过5个点)

复杂度分析:时间复杂度O(n.logn);空间复杂度

import java.util.*;
import java.io.*;

public class Main {
    
    

    static final Scanner cin = new Scanner(System.in);
    static long N = (long)1e8;
    static long k;

    //计算n中有多少个5
    public static long check(int num) {
    
    
        long res = 0L;
        while (num > 0) {
    
    
            res += num / 5;
            num /= 5;
        }
        return res;
    }

    public static void main(String[] args) {
    
    
        k = cin.nextLong();
        for (int i = 1; i <= N; i ++) {
    
    
            //找到第一个>=k情况
            long res = check(i);
            if (res >= k) {
    
    
                if (res == k) System.out.println(i);
                else System.out.println(-1);
                return;
            }
        }
        System.out.println(-1);
    }
}

image-20230311202306316


解法2:二分+算数基本定理

复杂度分析:时间复杂度O(logn*logn);空间复杂度O(1)

import java.util.*;
import java.io.*;

public class Main {
    
    

    static final Scanner cin = new Scanner(System.in);
    static long k;

    //计算n中有多少个5
    public static long check(long num) {
    
    
        long res = 0L;
        while (num > 0) {
    
    
            res += num / 5;
            num /= 5;
        }
        return res;
    }

    public static void main(String[] args) {
    
    
        k = cin.nextLong();
        //二分
        long l = 0, r = (long)9e18;
        while (l < r) {
    
    
            long mid = l + r >> 1;
            if (check(mid) >= k) r = mid;
            else l = mid + 1;
        }
        if (check(r) == k) {
    
    
            System.out.println(r);
        }else {
    
    
            System.out.println("-1");
        }
    }
}

image-20230311202542184


参考资料

[1]. 蓝桥杯官网真题视频+文字解析

猜你喜欢

转载自blog.csdn.net/cl939974883/article/details/129478896