质数-试除法

305 阅读1分钟

详解

质数是针对所有大于1的自然数定义的,所有小于等于1的数既不是质数也不是合数
质数 : 在大于1的整数中,如果只包含1和本身这两个约数,就称其为质数/素数。

质数判定

法一

超级暴力写法,从定义出发,时间复杂度是O(n)

bool is_prime(int n)
{
    if (n <= 1) return false;
    for (int i = 2; i < n; i ++ )
        if (n % i == 0)
            return false;
    return true;
}

法二

重要性质:若d|n,则(n/d)|n ,所以在枚举时,可以每次只枚举每一对中较小的一个即 d <= (n / d) => d * d <= n => d <= sqrt(n)这样的数, 时间复杂度是O(sqrt(n))

bool is_prime(int n)
{
    if (n <= 1) return false;
    /*
                    i < sqrt(n) 每次都会执行一次sqrt,所以很慢
                    i * i < n   n~2147483647时,会溢出 (Python可以这么写)
    */
    for (int i = 2; i < n / i; i ++ )
        if (n % i == 0)
            return false;
    return true;
}

分解质因数

思路:从2~n枚举所有数,当找到一个i可以整除n时,就进行循环,除掉所有的i(删掉所有质因子)。n中最多只包含一个大于sqrt(n)的质因子(若有俩,这两相乘铁定大于n)。时间复杂度是O(logn)

例题(AcWing.867. 分解质因数)

给定 nn 个正整数 aiai,将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。

输入格式

第一行包含整数 nn。

接下来 nn 行,每行包含一个正整数 aiai。

输出格式

对于每个正整数 aiai,按照从小到大的顺序输出其分解质因数后,每个质因数的底数和指数,每个底数和指数占一行。

每个正整数的质因数全部输出完毕后,输出一个空行。

数据范围

1≤n≤1001≤n≤100,
2≤ai≤2×1092≤ai≤2×109

输入样例:

2
6
8

输出样例:

2 1
3 1

2 3

代码

#include<iostream>
#include<algorithm>

using namespace std;

void divide(int n)
{
    for (int i = 2; i <= n / i; i ++ )
        if (n % i == 0) // i 一定是质数,因为2 ~ i - 1之间的质因子都被除掉了
        {
            int s = 0;
            while (n % i == 0)
            {
                n /= i;
                s ++ ;
            }
            printf("%d %d\n", i, s);
        }
    if (n > 1) printf("%d %d\n", n, 1);
    puts("");
}
int main()
{
    int n, x;
    scanf("%d", &n);
    while (n -- )
    {
        scanf("%d", &x);
        divide(x);
    }
    return 0;
}