埃氏筛法、区间筛法(求素数个数)

1、埃氏筛法

        给定整数n,请问n以内有多少个素数?(n≤106)

思路:首先,将2到n范围内的所有整数写下来。其中最小的数字2是素数。将表中所有2的倍数都划去。表中剩余最小的数字是3,它不能被更小的素数整除,所以是素数。再将表中3的倍数都划去。以此类推,如果表中最小的数字是m时, m 就是素数。像这样反复操作,就能以此枚举n以内的素数。

int pri[Max_n]; //第i个素数
bool vis[Max_n];//为false表示i是素数

int Prime(int n){
    int k=0;
    memset(vis,0,sizeof(vis));
    for(int i=2;i<=n;i++){
        if(!vis[i]){
            pri[k++]=i;
            for(int j=2*i;j<=n;j+=i)vis[j]=true;
        }
    }
    return k;
}

2、区间筛法

      给定整数a和b,请问区间[a,b)内有多少个素数?(a<b≤1012,b-a106

思路:b以内的合数的最小质因数一定不超过√b。如果有b以内的素数表的话,就可以把埃氏筛法运用在[a,b)上了。也就是说,先分别做好[2,b)的表和[a,b)的表,然后从[2,b)的表中筛得素数的同时,也将其倍数从[a,b)的表中划去,最后剩下的就是[a,b)内的素数了。

bool v1[Max_n1]; //数组大小为sqrt(b)
bool v2[Max_n2]; //数组大小为b-a

ll Prime(ll a,ll b){
    for(ll i=0;i*i<b;i++)v1[i]=true;
    for(ll i=0;i<b-a;i++)v2[i]=true;

    for(ll i=2;i*i<b;i++){
        if(v1[i]){
            for(ll j=2*i;j*j<b;j+=i)v1[j]=false; //筛[2,b)
            for(ll j=max(2LL,(a+i-1)/i)*i;j<b;j+=i)v2[j-a]=false; //筛[a,b)
            //2LL是2的长整数形式
            //((a+i-1)/i)*i是符合>=a最小是i倍数的数
        }
    }
    ll k=0;
    for(ll i=0;i<b-a;i++){
        if(v2[i])k++;
    }
    return k;
}
### 使用C语言在PTA平台上实现拉托斯特尼筛法区间素数 拉托斯特尼筛法是一种高效的算用于找出一定范围内的所有素数。对于给定的一个正整数n,该方可以有效地找到小于等于n的所有素数[^1]。 为了实现在特定区间[m, n]内寻找素数的功能,在实际编程过程中通常会先创建一个布尔类型的数组`isPrime[]`来标记哪些数字是素数。初始情况下假设所有的数值都是素数(即设置为true),之后通过遍历并更新这个数组中的元素状态完成筛选过程。当处理较大区间的查询时,考虑到内存使用的效率问题,建议只开辟大小约为sqrt(n)+1的空间存储必要的标志位即可满足需[^2]。 下面是一个具体的例子展示如何利用C语言编写程序以获取指定范围内所有质数: ```c #include <stdio.h> #include <string.h> #define MAXN 1000005 // 定义最大可能值加一作为上限 int prime[MAXN]; // 存储素数表 bool is_prime[MAXN]; // 判断是否为素数的辅助数组 void sieve(int max_val) { memset(is_prime, true, sizeof(bool)*(max_val+1)); int cnt = 0; for (long long i = 2; i <= max_val; ++i){ if (is_prime[i]){ prime[cnt++] = i; for (long long j=i*i;j<=max_val;j+=i) is_prime[j]=false; } } } // 找到m-n之间的所有素数 void find_primes_between_m_and_n(long m,long n){ bool mark[n-m+1]; memset(mark,true,sizeof(bool)*(n-m+1)); for (int p=0;p<MAXN && prime[p]*prime[p]<=n;++p){ long first_multiple=(m/prime[p])*prime[p]; if(first_multiple<m)first_multiple+=prime[p]; for(;first_multiple<=n;first_multiple+=prime[p]) mark[first_multiple-m]=false; if(first_modified==m)mark[0]=true; } printf("Primes between %ld and %ld:\n", m,n); for (long i=m;i<=n;++i) if (mark[i-m])printf("%ld ",i); } ``` 上述代码片段展示了完整的埃氏筛法逻辑以及针对任意两个边界值之间查找素数的具体操作。需要注意的是这里定义了一个较大的常量`MAXN`用来表示预估的最大输入规模,并据此分配相应的空间;而在具体应用中应当依据实际情况调整此参数取值[^3]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值