SP503 【PRINT - Prime Intervals】

筛出整数范围内的素数,对于区间[l, r],枚举合法的素数,然后标记他们的整数倍,显然被标记的就是[l, r]范围内的合数,那么暴力枚举剩下的素数输出即可。

这里只说明大体思路,具体细节会放在代码里。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<map>
#define ll long long //亦可写成 typedef long long ll

using namespace std;

const int maxn = 10000005;
bool p[maxn];
ll v[maxn], prime[maxn], l, r, m, a[maxn];
//v数组和prime数组用于线性筛,a数组记录答案,p数组标记[l, r]内的合数。

void pri(int n)
{
    memset(v, 0, sizeof(v));
     m = 0;
    for (int i = 2; i <= n; i++) {
        if (v[i] == 0) {
            v[i] = i;
            prime[++m] = i;
        }
        for( int j = 1; j <= m; j++) {
            if (prime[j] > v[i] || prime[j] > n / i) break; 
            v[i * prime[j]] = prime[j];
        }
    }
}

int main()
{ 
    pri(5e4+10);//线性筛
    int T;
    cin >> T;
    for (int i = 1; i <= T; i++) {
    cin >> l >> r;
    memset(p, 0, sizeof(p));//多测不清空,爆零两行泪
    if (l == 1) l = 2;
    // 跳过l == 1的情况,l  == 1没有任何意义
    for(ll j = 1; j <= m; j++) {
        for(ll i = l / prime[j]; i <= r / prime[j]; i++) {
            while (i <= 1) i++;
            if (prime[j] * i < l || prime[j] * i > r) continue;//保证在[l, r]内
            p[prime[j] * i - l] = 1;//标记合数
        }       
    }
    ll cnt = 0;
    for (ll i = l; i <= r; i++)
        if (p[i-l] == 0)
            a[++cnt] = i;//记录素数
    for (int i = 1; i <= cnt; i++) cout << a[i] << '\n';
	}
	return 0;
}

完结撒花~~

posted @ 2019-10-25 15:00  Hydrogen_Helium  阅读(147)  评论(0编辑  收藏  举报