对 质数筛法 和 质因数分解 的模版实验 - 数论

本文介绍了质数的定义及高效判断方法,并提供了C++实现示例。还讲解了质因数分解的概念及其应用,包括如何求解质因数及因子个数等,并给出了一种随机性素数判定算法——Miller-Rabin算法。

实验环境:win10
实验IDE:codeblocks

概念

  • 质数(prime number)又称素数,有无限个。质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数,这样的数称为质数。

素数判断

  • 按照定义,最暴力的素数判断方法是遍历(2-N-1)的所有数,看它能否被N整除,只要出现一个能整除的,它就不是素数。
  • 在我们数论中,素数有更高效的判断方法,就是只要判断2-sqrt(n)之间的数是否能整除N即可。具体代码如下。
#include <iostream>
#include <cmath>
using namespace std;

int is_prime(int N)
{
    int m=sqrt(N+0.5);
    for(int i=2;i<=m;i++)
        if(N%i==0) return 0;//不是素数
    return 1;//是素数
}
int main()
{
    cout<<is_prime(6);
    return 0;
}

关于预处理1-MAXN区间内的所有素数 - 质数筛法

备注
  • MAXN可以由自己定义,一般是求1e6内的质数。
  • 下面是 MAXN=100000 的示例,分别筛去 2,3,5…的倍数,剩下的就是质数了。
  • 这里写图片描述
    注:cnt为1-MAXN质数个数,上图第二行输出的是前100个素数。
  • 应用形式,若需要重复调用1-MAXN区间内的素数,可以先预处理,而不是再重新取素数(重新取素数又要重新判断,耗时)。
C++模版
#include <iostream>
#include <cmath>
using namespace std;

const int MAXN=100000;
bool vis[MAXN+1]={1,1};//假定0,1是质数,但其实不是.
int prime[MAXN+1];
int cnt=0;
void getPrime()
{
    int i,j;
    int m=sqrt(MAXN+0.5);
    for(i=2;i<=m;i++){
        if(!vis[i]){
            for(j=i*i;j<=MAXN;j+=i) vis[j]=1;
        }
    }
    for(i=2;i<=MAXN;i++){
        if(!vis[i]) prime[cnt++]=i;
    }
}
int main()
{
    getPrime();
    cout<<cnt;//输出1-MAXN内的质数个数
    return 0;
}

质因数分解

概念
  • 正整数的唯一分解定理:每个大于1的自然数n均可写为质数的积,而且这些素因子按大小排列之后,写法仅有一种方式:
    n=p1^e1*p2^e2*…pr^er……
    其中pi为质数,p1< p2< …< pr,且ei为正整数。
    • 结论一:因子个数(1+e1)(1+e2)…(1+er)
    • 结论二:n的所有因子之和:(1+p1+p1^2+…+p1^e1)(1+p2+p2^2+…+p2^e2)…*(1+pr+pr^2+…+pr^er)
C++模版
int fac[1000];//数组大小视具体情况而定
int cnt;
void getFactor(LL n)
{//求n的所有质因素
    cnt=0;
    LL m=sqrt(n+0.5);
    for(int i=2;i<=m&&n;i++){
        if(n%i==0){
            fac[cnt++]=i;
            while(n&&n%i==0) n/=i;
        }
    }
    if(n>1) fac[cnt++]=n;
}

随机性素数判定算法之Miller-Rabin算法

大数因数分解算法之Pollard-Rho算法

<think>嗯,用户现在想了解分解质因数的Java实现。之前他们问过滑动窗口的Java模板,现在转向另一个算问题。可能用户正在准备面试或者学习算,需要掌握不同问题的解决方分解质因数是一个数学问题,滑动窗口不同,属于数论范畴,但同样常见于编程题中。 首先,我需要回忆分解质因数的基本步骤。分解质因数指的是将一个正整数分解成若干个质数相乘的形式。例如,12分解2×2×3。那在Java中如何实现呢?通常的方是从最小的质数2开始,依次尝试整除,直到商为1为止。 用户之前得到过滑动窗口的模板,可能希望这里也有类似的模板或者分步说明。需要确保回答结构清晰,步骤明确,代码正确。同时要注意用户提到的系统级指令,比如数学表达式用$...$格式,中文回答,LaTeX语正确。 分解质因数的关键在于循环除以可能的因数,并记录这些因数。需要注意以下几点: 1. 处理输入为1的情况,因为1没有质因数2. 从2开始,逐个试除,直到平方根为止,因为一个数的因数不会超过它的平方根。 3. 每次找到一个因数后,尽可能多次除以该因数,直到无整除,再增加因数。 4. 如果最后剩下的数大于1,那么它本身也是一个质因数。 需要确保代码能够处理这些情况,并且输出正确的质因数列表。比如输入是12,输出应该是2 2 3。而输入是7,输出是7本身。 还要考虑代码的效率,避免不必要的循环。例如,当试除到sqrt(n)时,可以停止,但之后要检查剩下的n是否为1,否则需要加入最后的因数。 在编写Java代码时,可以使用一个循环,从i=2开始,直到i*i <=n,每次i递增。每次找到能整除的i时,循环除以i,并记录次数,直到无整除,再增加i。最后如果n>1,则加入结果。 可能还需要考虑输入的合性,比如n是否大于等于2,但题目可能假设输入是正整数,所以可能不需要处理负数或0的情况,但最好在代码中加入检查。 接下来,我需要将这些思路转化为结构化的回答,符合用户要求的模板,可能包括核心思想、代码模板、关键步骤解析、示例等。同时要使用中文,保持清晰的结构,帮助用户逐步理解如何实现分解质因数。</think>--- ### **分解质因数 Java 实现详解** --- #### **核心思想** 分解质因数是将一个正整数 $n$ 表示为**质数相乘**的形式,例如:$12 = 2 \times 2 \times 3$。算核心是通过**试除**,从最小的质数开始逐个尝试整除,直到商为 1--- ### **Java 代码模板** ```java import java.util.ArrayList; import java.util.List; public class PrimeFactorization { public static List<Integer> primeFactors(int n) { List<Integer> factors = new ArrayList<>(); // 处理偶数因子 while (n % 2 == 0) { factors.add(2); n /= 2; } // 处理奇数因子(只需检查到 sqrt(n)) for (int i = 3; i * i <= n; i += 2) { while (n % i == 0) { factors.add(i); n /= i; } } // 处理剩余的大于2质数 if (n > 2) { factors.add(n); } return factors; } public static void main(String[] args) { int num = 60; List<Integer> factors = primeFactors(num); System.out.println(num + "的质因数分解:" + factors); // 输出 [2, 2, 3, 5] } } ``` --- ### **关键步骤解析** 1. **处理偶数因子** 所有偶数都能被 2 整除,循环提取所有 2 的因子,将 $n$ 变为奇数。 2. **处理奇数因子** 从 3 开始,以步长 2 递增(跳过偶数),尝试每个奇数是否能整除 $n$。 每次找到一个因子 $i$,循环除以 $i$ 直到无整除。 检查范围到 $\sqrt{n}$ 即可,因为若 $n$ 有大于 $\sqrt{n}$ 的因子,另一个因子必然小于 $\sqrt{n}$。 3. **处理剩余因子** 如果最后 $n > 2$,说明 $n$ 本身是质数,直接加入结果。 --- ### **时间复杂度** - **最优情况**:$O(\log n)$(例如 $n = 2^k$,只需处理 2 的因子) - **最坏情况**:$O(\sqrt{n})$(当 $n$ 为质数时需要遍历到 $\sqrt{n}$) --- ### **示例分析** 以输入 $n=60$ 为例: 1. 提取 2:$60 \div 2 = 30$ → 再提取 2:$30 \div 2 = 15$ 2. 检查 3:$15 \div 3 = 5$ 3. 检查 5:$5 \div 5 = 1$ 最终质因数分解为 $[2, 2, 3, 5]$。 --- ### **特殊处理** - **输入为 1**:1 没有质因数,返回空列表。 - **输入为质数**:直接返回该数本身(如 $n=7$ → $[7]$)。 --- ### **优化技巧** 1. **预生成质数表**:对于大数,可先通过筛生成质数表再试除。 2. **提前终止条件**:当 $n=1$ 时立即退出循环。 3. **并行处理**:针对极大数,结合 Pollard's Rho 算加速分解--- ### **常见问题** 1. **为什么只检查到 $\sqrt{n}$?** 若 $n$ 有一个因子 $d > \sqrt{n}$,则另一个因子必为 $n/d < \sqrt{n}$,因此只需遍历到 $\sqrt{n}$。 2. **如何处理重复因子?** 通过 `while (n % i == 0)` 循环提取所有重复因子。 --- 掌握该模板后,可快速解决与质因数分解相关的算问题,例如计算最大公约数、最小公倍数或解决数论类题目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值