详解
质数是针对所有大于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;
}