• 数学问题——质因子分解


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

  • 相关阅读:
    java插入语句中有单引号的处理
    mybatis批量插入
    用Resttemple从数据接口中取出数据
    java1.8Stream流式算法
    rabbitmq启动命令
    【MySQL】Mysql模糊查询like提速优化
    Mybatis基础知识点:trim标签的使用
    java8 array、list操作 汇【20】)- (FlatMap)用法汇总
    编写一个定制的收集器
    mysql
  • 原文地址:https://www.cnblogs.com/coderJiebao/p/Algorithmofnotes14.html
Copyright © 2020-2023  润新知