题目大意
解题思路
埃式筛法的复杂度是 的。但是此题的范围是 因此不能使用埃式筛法。并且空间复杂度也不允许。但是我们可以借鉴埃式筛法的思想,它根据两个事实;
- (1) 以内的合数的最小质因数一定不超过 。即 且 是合数,因此其必有质因数小于
- (2) 做出 的质数表,并从 中划去所有质数倍数,剩下的就是质数。
因此为了解此题,我们需要维护一个
- :用来判断 范围内的数是否是素数。
由于数字太大,为了节省空间。我们维护一个
- : 来判断 是否是素数.
代码
#include<iostream>
using namespace std;
typedef long long ll;
const int MAXN = 1000000+5;
ll is_prime1[MAXN];
ll is_prime2[MAXN];
void get_primes(ll a, ll b)
{
// ------------初始化 --------------
for(ll i=0; i*i<b; i++)
is_prime1[i] = 1;
is_prime1[0] = is_prime1[1] = 0;
for(ll i=a; i<b; i++)
is_prime2[i-a] = 1;
// ---------------------------------
for(ll i=2; i*i<b; i++)
{
if(is_prime1[i])
{
// 筛is_primes1
for(ll j=(ll)2*i; j*j<b; j+=i)
is_prime1[j] = 0;
// 筛is_primes2
for(ll j=(ll)(a-1+i)/i*i; j<b; j+=i)
is_prime2[j-a] = 0;
}
}
}
int main()
{
ll a, b;
cin >> a >> b;
get_primes(a, b);
ll ans = 0;
for(ll i=a; i<b; i++)
{
if(is_prime2[i-a])
ans++;
}
cout << ans << endl;
}
知识点
- 上方的代码中有这么一行
j = (ll)(a-1+i)/i*i
。 是对 向上取整,因此此计算的作用是求得第一个 的 的倍数。