目录

裴先生
裴先生
发布于 2022-04-12 / 6 阅读
1
0

算法题:素数之积

原创

题目描述

RSA加密算法在网络安全世界中无处不在,它利用了极大整数因数分解的困难度,数据越大,安全系数越高。给定一个32位正整数,请对其进行因数分解,找出是哪两个素数的乘积。

输入输出要求

  • 输入:一个正整数 num(0 < num <= 2147483647)
  • 输出:如果成功找到,以单个空格分割,从小到大输出两个素数;分解失败,请输出 -1 -1

示例

示例1

  • 输入15
  • 输出3 5
  • 说明:因数分解后,找到两个素数3和5,使得3*5=15,按从小到大排列后,输出3 5。

示例2

  • 输入27
  • 输出-1 -1
  • 说明:通过因数分解,找不到任何素数,使得他们的乘积为27,输出-1 -1。

知识点补充

  1. 素数定义:如果一个数字不是素数,那它除了1和他本身一定还有别的约数。
  2. 优化搜索范围:如果一个数的约数在其开平方的右边,则必然会存在一个约数在其开平方的左边。
  3. 判断质数:判断一个数是否为质数,只需要观察在其 2 到 开平方数 中间是否含有约数即可。
    • 例如:判断16是否为质数,我们去找16的约数时,判断它的范围只需要找到 \sqrt{16} 就可以了,而不必一直找到 <16 或者 <= 16/2。

优化后的Java解法

import java.util.Scanner;

/**
 * RSA素数分解求解
 * 寻找两个素数使其乘积等于给定的整数
 * @since 2026-04
 */
public class ProductOfPrime {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        if (scanner.hasNextInt()) {
            int num = scanner.nextInt();
            solve(num);
        }
        scanner.close();
    }

    /**
     * 核心求解逻辑
     */
    private static void solve(int num) {
        int a = -1;
        int b = -1;
        
        // 只需要遍历到 num 的平方根
        // 因为如果 num = p * q,且 p <= q,那么 p 一定 <= sqrt(num)
        int limit = (int) Math.sqrt(num);
        
        for (int i = 2; i <= limit; i++) {
            // 1. 判断 i 是否为素数
            // 2. 判断 i 是否能整除 num
            if (isPrime(i) && num % i == 0) {
                int otherFactor = num / i;
                // 3. 判断另一个因子是否也为素数
                if (isPrime(otherFactor)) {
                    a = i;
                    b = otherFactor;
                    break; // 找到一组解后即可退出(题目隐含寻找一组解)
                }
            }
        }

        System.out.println(a + " " + b);
    }

    /**
     * 判断是否是素数
     * 时间复杂度: O(sqrt(n))
     *
     * @param arg 待判断的整数
     * @return 如果是素数返回true,否则返回false
     */
    public static boolean isPrime(int arg) {
        if (arg <= 1) {
            return false;
        }
        if (arg == 2) {
            return true;
        }
        if (arg % 2 == 0) {
            return false;
        }
        
        // 只需要判断到 sqrt(arg)
        int sqrt = (int) Math.sqrt(arg);
        for (int j = 3; j <= sqrt; j += 2) { // 从3开始,只判断奇数
            if (arg % j == 0) {
                return false;
            }
        }
        return true;
    }
}

原创

版权声明:本博客原创文章,由 裴先生 2022年04月12日 发表。
转载说明:除特殊说明外本站文章皆由 CC BY-NC-SA 4.0 协议发布,转载须注明出处。


评论