素数筛的C语言应用

总体思路:用素数来标记合数
具体步骤
1、用prime[i]来标记i是否是合数
2、标记为1的数字为合数,否则为素数
3、第一次知道2是素数,则将2的倍数标记为1
4、向后找到第一个没有被标记的数字i
5、将i的倍数全部标记为合数
6、重复4–6步,直到标记完范围内的所有数字
代码如下

#include <stdio.h>
#define max_n 100

int prime[max_n + 5] = {0};

void init() {
    for(int i = 2; i <= max_n; i++) {
        if(prime[i]) continue;      //若为1 即不是素数,退出本次循环
        prime[++prime[0]] = i;       //prime[0] 等同一个变量 将其看做++n,已经初始化n = 0,记录数据有多少个
        for(int j = i*i; j<= max_n; j += i) {     //改2 * i 为 i * i  
            prime[j] = 1;                         //、所以数组大小不能超过10 0000、
        }                                         //i * i超过整型的极大值,就表示为负数
    }
    return ;
}


int main() {
    init();
    for (int i = 1; i <= prime[0]; i++){
        printf("%d\t",prime[i]);
        if(i % 5 == 0) puts("\n");   //每5个数据换行输出 
    }
    puts("\n");
    printf("prime[0] = %d\n",prime[0 ]);
    return 0;
}

疑问:为什么素数筛的时间复杂度是0(loglongN),为何不是0(n^2)
da:总认为两层循环嵌套就是0(n^2),这是错误的思想,要看循环频率,外层循环一次,内层循环多少次,该方法外层循环一次,内层循环longlongN次,具体怎么算的是数论的东西,可以看这里埃拉托色尼筛法,经过改进又被称为线性时间筛法
即大家认为的o(n)时间复杂度(这里素数筛可看作约等于o(n))


函数的优化:
初始:

for(int i = 2; i <= max_n; i++) {
    if(prime[i]) continue;  //如果不是素数,推出本次循环
    for(int j = 2*i; j<= max_n; j += i) {
        prime[j] = 1;
    }
}

值得注意的是:一个小优化:避免了重复标记

 for(int j = i*i; j<= max_n; j += i) {     //改2 * i 为 i * i  
            prime[j] = 1;                         //、所以数组大小不能超过10 0000、
        }                                         //i * i超过整型的极大值,就表示为负数

再次优化:当i= 10 0000 时避免i * i的超出整型最大值

 for(int j = i; j<= max_n / i; j ++) {     //改2 * i 为 i * i  
            prime[j * i] = 1;                        
        }          
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值