花式玩转线性筛(线性筛法 + 算术基本定理)

利用(线性筛法O(n) + 算数基本定理) 基本上可以解决所有因子问题。

本文提供的方法:

1.计算任意数字的最小素因子

2.计算任意数字的最大素因子

3.计算任意数字的素因子种类数量

4.计算任意数字的因子个数

5.计算任意数字的因子和

1.计算任意数字的最小质因子

#include <stdio.h>
#define MAX_N 1000000
#define MIN(a,b) (a) > (b) ? (b):(a)
int prime[MAX_N + 5] = {0};
int dnum[MAX_N + 5] = {0};
void init(){
    for (int i= 2; i <= MAX_N; ++i){
        if (!prime[i]){
            prime[++prime[0]] = i;
            dnum[i] = i;
        }
        for (int j = 1; j <= prime[0]; ++j){
            if (i * prime[j] >= MAX_N){
                break;
            }
            prime[i * prime[j]] = 1;
            dnum[i * prime[j]] = MIN(dnum[i],dnum[prime[j]]);
            if (i % prime[j] == 0) break;
        }
    }
}
int main(){
    int n;
    init();
    while (~scanf("%d", &n)){
        printf("%d\n", dnum[n]);
    }
    return 0;
}

2.计算任意数字的最大质因子

#include <stdio.h>
#define MAX_N 1000000
#define MIN(a,b) (a) > (b) ? (b):(a)
#define MAX(a,b) (a) > (b) ? (a):(b)
int prime[MAX_N + 5] = {0};
int dnum[MAX_N + 5] = {0};
void init(){
    for (int i= 2; i <= MAX_N; ++i){
        if (!prime[i]){
            prime[++prime[0]] = i;
            dnum[i] = i;
        }
        for (int j = 1; j <= prime[0]; ++j){
            if (i * prime[j] >= MAX_N){
                break;
            }
            prime[i * prime[j]] = 1;
            dnum[i * prime[j]] = dnum[i];
            if (i % prime[j] == 0) {
                break;
            }
        }
    }
}
int main(){
    int n;
    init();
    while (~scanf("%d", &n)){
        printf("%d\n", dnum[n]);
    }
    return 0;
}

3.计算任意数字的质因子种类数量

#include <stdio.h>
#define MAX_N 1000000
#define MIN(a,b) (a) > (b) ? (b):(a)
#define MAX(a,b) (a) > (b) ? (a):(b)
int prime[MAX_N + 5] = {0};
int dnum[MAX_N + 5] = {0};
void init(){
    for (int i= 2; i <= MAX_N; ++i){
        if (!prime[i]){
            prime[++prime[0]] = i;
            dnum[i] = 1;
        }
        for (int j = 1; j <= prime[0]; ++j){
            if (i * prime[j] >= MAX_N){
                break;
            }
            prime[i * prime[j]] = 1;
            dnum[i * prime[j]] = dnum[i] + (i % prime[j] != 0);
            if (i % prime[j] == 0) {
                break;
            }
        }
    }
}
int main(){
    int n;
    init();
    while (~scanf("%d", &n)){
        printf("%d\n", dnum[n]);
    }
    return 0;
}

4.计算任意数字的因子个数

#include <stdio.h>
#define MAX_N 1000000
#define MIN(a,b) (a) > (b) ? (b):(a)
#define MAX(a,b) (a) > (b) ? (a):(b)
int prime[MAX_N + 5] = {0};
int dnum[MAX_N + 5] = {0};
void init(){
    for (int i= 2; i <= MAX_N; ++i){
        if (!prime[i]){
            prime[++prime[0]] = i;
            dnum[i] = 2;
        }
        for (int j = 1; j <= prime[0]; ++j){
            if (i * prime[j] >= MAX_N){
                break;
            }
            prime[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                int cnt = 0;
                int temp = i;
                while (temp % prime[j] == 0){
                    temp /= prime[j];
                    cnt++;
                }
                dnum[i * prime[j]] = dnum[i] / (cnt + 1) * (cnt + 2);
                break;
            }else{
                dnum[i * prime[j]] = dnum[i] * dnum[prime[j]];
            }
        }
    }
}
int main(){
    int n;
    init();
    while (~scanf("%d", &n)){
        printf("%d\n", dnum[n]);
    }
    return 0;
}

5.计算任意数字的因子和

#include <stdio.h>
#include <math.h>
#define MAX_N 1000000
#define MIN(a,b) (a) > (b) ? (b):(a)
#define MAX(a,b) (a) > (b) ? (a):(b)
int prime[MAX_N + 5] = {0};
int dnum[MAX_N + 5] = {0};
void init(){
    dnum[1] = 1; ///初始值
    for (int i= 2; i <= MAX_N; ++i){
        if (!prime[i]){
            prime[++prime[0]] = i;
            dnum[i] = i + 1;
        }
        for (int j = 1; j <= prime[0]; ++j){
            if (i * prime[j] >= MAX_N){
                break;
            }
            prime[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                int temp = i;
                int cnt = 0;
                while (temp % prime[j] == 0){
                    cnt++;
                    temp /= prime[j];
                }
                dnum[i * prime[j]] = dnum[temp] * ((pow(prime[j], cnt + 2) - 1) / (prime[j] - 1));
                break;
            }else{
                dnum[i * prime[j]] = dnum[i] * dnum[prime[j]];
            }
        }
    }
}
int main(){
    int n;
    init();
    while (~scanf("%d", &n)){
        printf("%d\n", dnum[n]);
    }
    return 0;
}

PS:细心的同学可能会发现我的所有for都是++i,因为i++存在弹栈操作相对较慢一些。

PS2:代码格式很重要!


猜你喜欢

转载自blog.csdn.net/Ruger008/article/details/80245687