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;
}
完结撒花~~