数学问题——质因子分解

  所谓质因子分解是指将一个正整数 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)。

 

posted @ 2018-01-18 11:29  Just_for_Myself  阅读(1773)  评论(0编辑  收藏  举报