Legendre公式

  • 📌 博主简介: 💻 努力学习的 23 级 软件工程专业 本科生一枚 🚀
  • 🏠 博主主页📎 @灰阳阳
  • 📚 往期回顾🌿 最小生成树——prim算法
  • 💬 每日一言“🌬️ 风不问归途,只管吹开花影 ✨”


一、Legendre 公式简介

1. 公式概述

所需参数:

  • n : n n n是一个正整数
  • p : p p p是一个小于等于 n n n的质数。

输出结果:

  • x :通过Legendre公式可以计算出 n ! n! n! 的其中一个约数 p x p^x px x x x的最大值。

我们可以用唯一分解定理来直观理解:
唯一分解定理表明,任何正整数都可以唯一地表示为质数的幂的乘积, n ! n! n! 也不例外:
n ! = p 1 e 1 p 2 e 2 … p k e k n! = p_1^{e_1} p_2^{e_2} \dots p_k^{e_k} n=p1e1p2e2pkek ,其中 p i p_i pi是唯一分解后的质数, e k e_k ek是对应的 p i p_i pi的幂次。
给定两个参数 n n n p i p_i pi,就能求出 p i p_i pi的最高次幂 e i e_i ei


2. 算法模板

import java.util.Scanner;
public class 求n的阶乘中x的最高次幂 {

    
    // 使用 Legendre 公式计算n!中质数p的最大幂次
    /**
     * @param n 正整数
     * @param p p是质数,并且p<=n
     */
    public static int legendreExponent(int n, int p) {
            int exp=0;//统计p的幂次
        while(n>0){
            exp+=(n/p);
            n/=p;
        }
        return exp;
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入阶乘的数值n:");
        int n = scanner.nextInt();
        System.out.println("请输入质数p:");
        int p = scanner.nextInt();
        int exponent = legendreExponent(n, p);
        System.out.println("在" + n + "!中,质数" + p + "的指数为:" + exponent);
        scanner.close();
    }
}

二、例题讲解

题目连接


1. 题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

定义阶乘 n ! = 1 × 2 × 3 × ⋯ × n n! = 1 \times 2 \times 3 \times \dots \times n n!=1×2×3××n

请问 100 ! 100! 100! (100 的阶乘)有多少个正约数。

运行限制

  • 最大运行时间:1s
  • 最大运行内存:128M

2. 解题思路

100 ! 100! 100! 是一个非常庞大的数字,如果直接暴力枚举其中的每一个数字,一定会超时。

  1. 我们可以用唯一分解定理,将其分解成有限个质数: n ! = p 1 e 1 p 2 e 2 … p k e k n! = p_1^{e_1} p_2^{e_2} \dots p_k^{e_k} n=p1e1p2e2pkek

  2. 可以发现 n ! n! n!的所有正约数就在这个集合:{ p 1 0 , … p 1 e 1 , p 2 0 , … p 2 e 2 , … , p k 0 , … p k e k p_1^{0}, \dots p_1^{e_1} ,p_2^{0}, \dots p_2^{e_2}, \dots ,p_k^{0}, \dots p_k^{e_k} p10,p1e1,p20,p2e2,,pk0,pkek }

  3. 因此 100 ! 100! 100! 的正约数个数就是 ∏ i = 1 k ( e i + 1 ) \prod_{i=1}^{k} (e_i+1) i=1k(ei+1)

  4. e i e_i ei可以通过枚举1-100中所有的质数 p i p_i pi计算获得,最终计算出答案。

tips: ∏ i = 1 k ( e i + 1 ) \prod_{i=1}^{k} (e_i+1) i=1k(ei+1) 是累乘的意思


3. AC代码

import java.math.BigInteger;

public class Main {
    // 判断是否为质数
    public static boolean isPrime(int num) {
        if (num < 2) return false;
        for (int i = 2; i <= Math.sqrt(num); i++) {
            if (num % i == 0) return false;
        }
        return true;
    }

    // 使用 Legendre 公式计算n!中质数p的最大幂次
    /**
     * @param n 正整数
     * @param p p是质数,并且p<=n
     */
    public static int legendreExponent(int n, int p) {
       int exp=0;
       while(n>0){
           exp+=(n/p);
           n/=p;
       }
       return exp;
    }


    public static void main(String[] args) {

        BigInteger ans=BigInteger.ONE;//因为要累乘,所以这里必须是1,不能是0

        //枚举1-100的所有质数,计算n!中i的最高次幂(i+1)进行累乘
        int n=100;
        for(int i=2;i<=100;i++){

            //是质数就进行计算(100!唯一分解后,1-100中所有质数一定都有贡献)
            if(isPrime(i)){
                ans=ans.multiply(BigInteger.valueOf(legendreExponent(n,i)+1));
            }
        }
        System.out.println(ans.toString());
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值