筛素数好题。题意:几乎是素数的数是这样一种数,它不是素数,但是它只有一个素因子。比如:4,8,9等。现在给你一个区间,让你统计区间内几乎是素数的数的个数。
我的解题思路:这个区间范围很大,右端点可以达到10的12次方。分析一下可以知道几乎是素数的数是素数的n次方(n > 2)。因此筛素数的范围到10的6次方就可以了。因为区间范围大,但是统计的数却不多,因此我们可以把最大范围内的几乎素数存起来,排序,然后根据输入的区间左右端点二分查找就可以了。
我的解题代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long Long;
const int N = 1000002;
const Long M = 1000000000001;
bool isprime[N];
Long primes[N], pn;
Long num[N], nn;
Long left, right;
void InitRead();
void DataProcess();
void FastSieve(int maxn);
int BinarySearch(Long key);
bool Mycmp(Long a, Long b)
{
return a < b;
}
int main()
{
int t;
InitRead();
scanf("%d", &t);
while (t--)
{
DataProcess();
}
return 0;
}
void InitRead()
{
memset(isprime, true, sizeof(isprime));
isprime[0] = isprime[1] = false;
pn = nn = 0;
FastSieve(N-1);
for (int i=0; i<pn; ++i)
{
Long temp = primes[i] * primes[i];
while (temp < M)
{
num[nn++] = temp;
temp *= primes[i];
}
}
sort(num, num+nn, Mycmp);
return;
}
void DataProcess()
{
scanf("%lld %lld", &left, &right);
int l = BinarySearch(left), r = BinarySearch(right);
if (num[l] == left)
{
printf("%d\n", r - l + 1);
}
else
{
printf("%d\n", r - l);
}
return;
}
void FastSieve(int maxn)
{
for (int i=2; i<=maxn; ++i)
{
if (isprime[i]) primes[pn++] = i;
for (int j=0; j<pn; ++j)
{
if (i * primes[j] > maxn) break;
isprime[i * primes[j]] = false;
if (i % primes[j] == 0) break;
}
}
return;
}
int BinarySearch(Long key)
{
if (key < 4) return -1;
int low = 0, high = nn - 1, mid;
while (low <= high)
{
mid = (high + low) >> 1;
if (num[mid] == key) return mid;
if (num[mid] > key) high = mid - 1;
else low = mid + 1;
}
return num[mid] < key ? mid : mid - 1;
}