试除法判断质数、分解质因数

c++

/*
 * 试除法判断质数、分解质因数
 * 本次将要介绍关于质数两个比较常见的算法,试除法判断质数和分解质因数
 *
 * 质数定义:
 *      质数,又叫素数,是指一个大于1的自然数,且除了1和它本身外,不能被其他自然数整除的数。换句话说,就是该数除了1 和它本身以外,不再有其他的因数。
 *
 * 算法 1. 试除法判断质数:
 *    算法流程:
 *      试除法判断质数是从质数的定义出发,对待判断的数字 x 而言,从 2 -> x - 1,判断是否可以被整除。 O(N) 复杂度。
 *      但是考虑到倘若 x 存在因数 a, 那么 b = x / t, b 也是 x 的因数,并且 x = a * b。假设 a != 1 && a != x,
 *      那么 a, b 中至少存在一个数字 <= sqrt(x),也就是使用试除法便利因数的时候,最高需要到 sqrt(n),复杂度优化到 O(N ^ 0.5)
 *    注意点:
 *      需要特判 x == 1 这种情况
 *
 * 算法 2. 分解质因数
 *    问题描述:
 *      给定一个正整数 x,现需要将其分解为质因数的乘积形式。
 *    朴素算法:
 *      首先筛选出素数,而后便利小于等于 x 的素数,将 x 分解,并注意在分解过程中 x 是不断更新变小的。
 *      素数塞的复杂度为 O(N) + 分解复杂度 O(N)
 *    跳跃方法:
 *      我们对  x 因数从小到大分解过程中,即使不预先筛选素数,其实也只有素数被选出来,因为我们分解 x 过程中总是先遇到质数。
 *      其次,也不必便利到 x - 1, 因为 sqrt (x) 也除以不了的话,就说明剩余更新的 x 也是一个质数。
 *      复杂度 O(log N) + O(sqrt(N)) = O(N ^ 0.5)
 */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>

using namespace std;

typedef pair<int, int> PII;
int n;

// 试除法判断质数
bool is_prime(int x) {
    if (x <= 1) {   // 这里需要特判一下
        return false;
    }

    double t = sqrt(x);
    for (int i = 2; i <= t; i ++ ) {    // sqrt(x)
        if (x % i == 0) {
            return false;
        }
    }
    return true;
}


// 分解质因数
vector<PII> decompose_prime(int x) {
    vector<PII> res;
    int cnt = 0;
    for (int i = 2; i <= sqrt(x); i ++ ) {  // sqrt (x)
        if (x % i == 0) {
            cnt = 0;
            while (x % i == 0) {    // 注意这里是 while 循环
                cnt += 1;
                x /= i;
            }
            res.push_back(PII(i, cnt));
        }
    }

    if (x != 1) {           // 如果 x != 1,就说明 x 是剩余的质数
        res.push_back(PII(x, 1));
    }
    return res;
}


int main()
{
    scanf("%d", &n);
    int x;
    while (n -- ) {
        scanf("%d", &x);
        vector<PII> res = decompose_prime(x);
        for (int i = 0; i < res.size(); i ++ ) {
            printf("%d %d\n", res[i].first, res[i].second);
        }
        printf("\n");
    }
    return 0;
}

posted @ 2022-06-25 14:30  lucky_light  阅读(330)  评论(0编辑  收藏  举报