给定两个整数L和R (L <= R)。任务是找到L到R(均包括两端)范围内的所有平方自由半素数。
例子:
Input : L = 1, R = 10
Output : 2
4, 6, 9, 10 are semi primes. But 6, 10 are square free semi primes.
Input : L = 10, R = 20
Output : 3
先决条件: Eratosthenes筛,上下限
理解 :
半素数是形式的数字其中p和q是质数,不一定是质数。全部半质数只有四个因素其中p和q是仅有的两个素数因子,并且 。
天真的方法:
预先计算所有素数 。找出两个素数p和q的所有组合,使得在L和R之间。遍历素数的所有组合将使时间复杂度为 。但是,该解决方案不适用于较大的L和R值。
时间复杂度: O(N ^ 2)
高效方法:
预先计算所有素数 。我们可以将找到两个质数p和q的问题分为一个简单的形式。
作为我们可以说 。类似我们可以说 。
现在问题被简化为找到q的计数,使得对于所有p。
在这里,我们可以使用二进制搜索来找到从素数列表中减去它的lower_bound的索引从素数列表中找到范围内所有q的计数至对于给定的p 。对所有素数p重复上述步骤,将给出给定范围L至R的答案
下面是上述方法的实现:
// CPP program to find square free semiprimes in the range
#include
using namespace std;
#define N 78498
void Sieve(int pre[])
{
// Max size of prime array
int MX = 1e6;
// Array of prime of size 1000001.
// will be marked true for prime, false otherwise
// i = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]
// prime = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, ...}
bool prime[MX + 1];
// i -> keeps track of index of prime
// (current integer)
// idx -> keeps track of index of pre
int i = 2;
int idx = 0;
// Initialize all entries to true
memset(prime, true, sizeof(prime));
// For all i from 2 to MX iterate
for (i = 2; i <= MX; i++)
{
// If i is prime
if (prime[i])
{
// Set idx'th index of pre as i and
// increment idx after setting the value
pre[idx++] = i;
// For all multiple of i from 2*i to MX
// mark them as false i.e. not prime
for (int j = (i << 1); j <= MX; j += i)
prime[j] = false;
}
}
}
// Function to find square free semi primes in the range
int semiPrimeCount(int L, int R)
{
// Array of prime integer
// will contain first 78498 primes
// idx = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]
// pre = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, ...}
int pre[N];
// Prepare pre array
Sieve(pre);
// Result of current query
int res = 0;
// Offset index from start
int j = 1;
// For all prime integers p in pre
// from 2 to sqrt(R) iterate
for (auto p : pre) {
// ub_num = count of all multiple of p less
// than R => p = R/p
//
// ub = iterator of first element greater
// than ub_num in pre
//
int ub_num = R / p;
auto ub = upper_bound(pre + j, pre + N, ub_num);
// lb_num = count of all multiple of p
// less than L => p = L/p
// If L is divisible by p increment p by
// 1 => p = p+1 = p+(L%p>0)
//
// lb = iterator of first element greater
// than or equal lb_num in pre
int lb_num = (L / p) + ((L % p) > 0);
auto lb = lower_bound(pre + j, pre + N, lb_num);
// Add the difference between ub and lb
res += ub - lb;
// Increment j
j++;
// If prime p is greater than or equal to sqrt(R)
if (p * p >= R)
break;
}
return res;
}
// Driver code
int main()
{
int L = 10, R = 20;
// Function call
cout << semiPrimeCount(L, R);
return 0;
}
输出:
3
时间复杂度: O(N * logN)