所谓质因子分解是指将一个正整数 n 写成一个或多个质数的乘积形式,例如 24=2*2*2*3。显然,由于最后都要归结到若干不同质数的乘积,不妨先把素数表打印出来。
由于每个质因子都可以不止出现一次,因此不妨定义结构体 factor ,用来存放质因子及其个数,如下所示:
1 struct factor { 2 int x, cnt; // x 为质因子,cnt 为其个数 3 } fac[10];
而有一个结论:对一个正整数 n 来说,如果它存在 [2,n] 范围内的质因子,要么这些质因子全部小于等于 sqrt(n) ,要么只存在一个大于 sqrt(n) 的质因子,而其余质因子全部小于等于 sqrt(n) 。这就给进行质因子分解提供了一个很好的思路:
1. 枚举 1~sqrt(n) 范围内的所有质因子 p,判断 p 是否是 n 的因子。如果 p 是 n 的因子,那么给 fac 数组中增加质因子 p ,并初始化其个数为 0。然后只要 p 还是 n 的因子,就让 n 不断除以 p,每次操作令 p 的个数加 1,直到 p 不再是 n 的因子为止。
1 if(n % pri[i] == 0) { // prime[i] 是质因子 2 fac[num].x = pri[i]; 3 fac[num].cnt = 0; 4 while(n%pri[i] == 0) { // 计算该质因子的个数 5 fac[num].cnt++; 6 n /= pri[i]; 7 } 8 num++; // 不同质因子个数 +1 9 }
2. 如果在上面步骤结束后 n 仍然大于 1,说明 n 有且仅有一个大于 sqrt(n) 的质因子,这时需要把这个质因子加入 fac 数组,并令其个数为 1。
1 if(n != 1) { // 存在大于 sqrt(n) 的质因子 2 fac[num].x = n; 3 fac[num++].cnt = 1; 4 }
至此,fac 数组中存放的就是质因子分解的结果,时间复杂度为O($\sqrt{n}$)。
【PAT A1059】Prime Factors
题目:Given any positive integer N, you are supposed to find all of its prime factors, and write them in the format N = p1^k1 * p2^k2 *…*pm^km.
题意:给出一个 int 范围的整数,按照从小到大的顺序输出其分解为质因数的乘法算式。
思路:见上面讲解
下面为程序的完整代码:
/* 质因子分解 */ #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #include <time.h> #include <stdbool.h> typedef struct{ int x, cnt; // x 为质因子,cnt 为其个数 } factor; factor fac[10]; #define maxn 100010 int pri[maxn], pNum=0; bool p[maxn] = {0}; // 表示数是否被筛掉 // 素数表的获取,埃氏筛选 void findPrime() { int i; for(i=2; i<maxn; ++i) { if(!p[i]) { // 没有被筛掉,为素数 pri[pNum++] = i; int j; for(j=i+i; j<maxn; j+=i) { // 筛掉倍数 p[j] = true; } } } } int num=0; // 表示 n 不同质因子个数 void findFactor(int n) { if(n==1) return; int sqr = (int)sqrt(n*1.0); int i; for(i=0; i<pNum && pri[i]<=sqr; ++i) { // 枚举 1~sqrt(n) 的所有质因子 if(n % pri[i] == 0) { // prime[i] 是质因子 fac[num].x = pri[i]; fac[num].cnt = 0; while(n%pri[i] == 0) { // 计算该质因子的个数 fac[num].cnt++; n /= pri[i]; } num++; // 不同质因子个数 +1 } if(n == 1) break; } if(n != 1) { // 存在大于 sqrt(n) 的质因子 fac[num].x = n; fac[num++].cnt = 1; } } int main() { findPrime(); // 生成素数表 int n; scanf("%d", &n); findFactor(n); // 求质因子 int i; // 按格式输出 printf("%d=", n); if(n==1) printf("1"); else { for(i=0; i<num; ++i) { if(i>0) printf("*"); printf("%d", fac[i].x); if(fac[i].cnt > 1) { printf("^%d", fac[i].cnt); } } } return 0; }
最后指出,如果要求一个正整数 N 的因子个数,只需要对其质因子分解,得到各质因子 pi 的个数分别为 e1、e2、... 、ek,于是 N 的因子个数就是 (e1 + 1)*(e2 + 1)*...*(ek + 1)。