- 📌 博主简介: 💻 努力学习的 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!=p1e1p2e2…pkek ,其中 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! 是一个非常庞大的数字,如果直接暴力枚举其中的每一个数字,一定会超时。
-
我们可以用唯一分解定理,将其分解成有限个质数: 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!=p1e1p2e2…pkek
-
可以发现 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 }
-
因此 100 ! 100! 100! 的正约数个数就是 ∏ i = 1 k ( e i + 1 ) \prod_{i=1}^{k} (e_i+1) ∏i=1k(ei+1)
-
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());
}
}