原理:一个数的倍数肯定不是素数
若给定子区间[fst, lst]
则必有区间内任意数最大的因子是sqrt(lst);
因此只需要将2 - sqrt(lst)中的所有质数的倍数从区间[fst, lst]中划掉即可
剩下的就是区间内的素数
注意两个情况
1. 第一次筛出的素数就在区间里 要特判
2. 将区间[fst, lst]映射入[0, lst - fst]
3.bitset优化
例题 https://www.acwing.com/problem/content/198/
代码:
/*
Zeolim - An AC a day keeps the bug away
*/
//pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <sstream>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const ld PI = acos(-1.0);
const ld E = exp(1.0);
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 10;
const ll MOD = 1e9 + 7;
vector <ll> getprime(ll n, ll m)
{
vector <ll> pri;
bitset <MAXN> used(0), rused(0);
ll len = sqrt(m);
for(int i = 2; i <= len; ++i)
{
if(!used[i])
{
ll x = i, y = max(x, x * (n / x));
while(y <= m)
{
if(y - n >= 0 && y != x)
rused[y - n] = true;
y += x;
}
for(int j = 2 * i; j <= len; j += i)
{
used[j] = true;
}
}
}
for(int i = 0; i <= m - n; ++i)
{
if(i + n >= 2 && !rused[i])
pri.push_back(i + n);
}
return pri;
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
//freopen("D://test.in", "r", stdin);
//freopen("D://test.out", "w", stdout);
ll n, m;
while(scanf("%lld%lld", &n, &m) != EOF)
{
getprime(n, m);
vector <ll> rpri = getprime(n, m);
int cha = -1, pa = -1, pb = -1;
int rcha = INF, rpa = -1, rpb = -1;
for(int i = 1; i < rpri.size(); ++i)
{
int val = rpri[i] - rpri[i - 1];
if(val > cha)
{
cha = val, pa = rpri[i - 1], pb = rpri[i];
}
if(val < rcha)
{
rcha = val, rpa = rpri[i - 1], rpb = rpri[i];
}
}
if(cha > 0)
printf("%d,%d are closest, %d,%d are most distant.
", rpa, rpb, pa, pb);
else
printf("There are no adjacent primes.
");
}
return 0;
}