对于 Q 查询,不同互质对乘积除以索引 [L, R] 中的所有元素的计数
给定一个包含N个整数的数组arr[]和(l, r)形式的Q个查询。任务是为每个查询找到不同的互素整数对的数量,使得索引范围[l, r]中的所有整数都可以被互素整数的乘积整除。
例子:
Input: arr[] = {1, 2, 2, 4, 5}, queries[] = {{2, 3}, {2, 4}, {3, 4}, {4, 4}, {4, 5}}
Output: 3 3 3 5 1
Explanation: For 1st query [2, 3], the subarray is {2, 2}.
The pairs of coprimes that divide all the integers in the subarray are {1, 1}, {1, 2} and {2, 1}.
For 2nd query [2, 4], the subarray is {2, 2, 4}.
The pairs of coprimes that divide all the integers are {1, 1}, {1, 2} and {2, 1}.
Similarly, proceed for the further queries.
Input: arr[] = {20, 10, 15}, queries[] = {{2, 3}, {1, 3}, {1, 2}}
Output: 3 3 9
方法:给定的问题可以在稀疏表的帮助下得到最佳解决。该方法基于这样一个事实,即只有子阵列的 GCD 的主要因素才能划分其所有元素。因此,GCD 的主要因素有助于对数的计数。可以使用稀疏表优化计算范围的 GCD。以下是要遵循的步骤:
- 创建一个稀疏表以在多个查询中以最佳时间查找范围[L, R]中的 GCD 元素。
- 遍历查询数组并对每个查询执行以下操作:
- 查找当前查询的[L, R]范围内元素的 GCD。
- 现在问题被简化为在[1, GCD]范围内找到其乘积为GCD的互质数对的数量,这可以使用此处讨论的算法来完成。
以下是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
#define MAXN 200001
int table[1001][1001];
// Function to build sparse table
void buildSparseTable(vector arr, int n)
{
// GCD of single element is
// the element itself
for (int i = 0; i < n; i++)
table[i][0] = arr[i];
// Build sparse table
for (int j = 1; j <= log2(n); j++)
for (int i = 0; i <= n - (1 << j);
i++)
table[i][j]
= __gcd(table[i][j - 1],
table[i + (1 << (j - 1))][j - 1]);
}
// Function to return the GCD of
// all elements in range [L, R]
int find_gcd(int L, int R)
{
// Highest power of 2 that is not
// more than count of elements
int j = (int)log2(R - L + 1);
// Return GCD in range
return __gcd(table[L][j],
table[R - (1 << j) + 1][j]);
}
// Smallest prime factors array
int spf[MAXN];
// Function to build the smallest
// prime factor array using Sieve
void build_spf()
{
spf[1] = 1;
for (int i = 2; i < MAXN; i++)
spf[i] = i;
for (int i = 4; i < MAXN; i += 2)
spf[i] = 2;
for (int i = 3; i * i < MAXN; i++) {
if (spf[i] == i) {
for (int j = i * i; j < MAXN;
j += i)
if (spf[j] == j)
spf[j] = i;
}
}
}
// Function to find the count of
// distinct prime factors of x
int getFactorization(int x)
{
// Stores the required count
int ctr = 0;
while (x != 1) {
ctr++;
// Stores smallest prime
// factor of x
int p = spf[x];
while (x % p == 0)
x = x / p;
}
// Return count
return ctr;
}
// Function to count of coprime pairs such
// that the product of the pair divides
// all integers of subarray in given range
void solveQueries(vector a, int n,
vector > q)
{
// Loop to iterate over queries
for (int i = 0; i < q.size(); i++) {
int l = q[i][0];
int r = q[i][1];
l--;
r--;
// Stores gcd in the range
int gcd = find_gcd(l, r);
// Stores the required count
int ans = 0;
// Count the pairs of co-primes
// integers in given format
for (int i = 1; i * i <= gcd; i++) {
// If i is a factor of gcd
if (gcd % i == 0) {
ans = and + (1 << getFactorization(i));
if (gcd / i != i)
ans += (1
<< getFactorization(gcd / i));
}
}
// Print answer
cout << ans << " ";
}
}
// Function to perform precomputation
void preProcess(vector a, int n)
{
build_spf();
buildSparseTable(a, n);
}
// Driver Code
int main()
{
vector arr = { 1, 2, 2, 4, 5 };
vector > queries = {
{ 2, 3 }, { 2, 4 }, { 3, 4 }, { 4, 4 }, { 4, 5 }
};
preProcess(arr, arr.size());
solveQueries(arr, arr.size(), queries);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
class GFG{
static final int MAXN = 200001;
static int [][]table = new int[1001][1001];
// Function to build sparse table
static void buildSparseTable(int[] arr, int n)
{
// GCD of single element is
// the element itself
for (int i = 0; i < n; i++)
table[i][0] = arr[i];
// Build sparse table
for (int j = 1; j <= Math.log(n); j++)
for (int i = 0; i <= n - (1 << j);
i++)
table[i][j]
= __gcd(table[i][j - 1],
table[i + (1 << (j - 1))][j - 1]);
}
static int __gcd(int a, int b)
{
return b == 0? a:__gcd(b, a % b);
}
// Function to return the GCD of
// all elements in range [L, R]
static int find_gcd(int L, int R)
{
// Highest power of 2 that is not
// more than count of elements
int j = (int)Math.log(R - L + 1);
// Return GCD in range
return __gcd(table[L][j],
table[R - (1 << j) + 1][j]);
}
// Smallest prime factors array
static int []spf = new int[MAXN];
// Function to build the smallest
// prime factor array using Sieve
static void build_spf()
{
spf[1] = 1;
for (int i = 2; i < MAXN; i++)
spf[i] = i;
for (int i = 4; i < MAXN; i += 2)
spf[i] = 2;
for (int i = 3; i * i < MAXN; i++) {
if (spf[i] == i) {
for (int j = i * i; j < MAXN;
j += i)
if (spf[j] == j)
spf[j] = i;
}
}
}
// Function to find the count of
// distinct prime factors of x
static int getFactorization(int x)
{
// Stores the required count
int ctr = 0;
while (x != 1) {
ctr++;
// Stores smallest prime
// factor of x
int p = spf[x];
while (x % p == 0)
x = x / p;
}
// Return count
return ctr;
}
// Function to count of coprime pairs such
// that the product of the pair divides
// all integers of subarray in given range
static void solveQueries(int [] a, int n,
int [][] q)
{
// Loop to iterate over queries
for (int i = 0; i < q.length; i++) {
int l = q[i][0];
int r = q[i][1];
l--;
r--;
// Stores gcd in the range
int gcd = find_gcd(l, r);
// Stores the required count
int ans = 0;
// Count the pairs of co-primes
// integers in given format
for (int j = 1; j * j <= gcd; j++) {
// If i is a factor of gcd
if (gcd % j == 0) {
ans = ans + (1 << getFactorization(j));
if (gcd / j != j)
ans += (1
<< getFactorization(gcd / j));
}
}
// Print answer
System.out.print(ans+ " ");
}
}
// Function to perform precomputation
static void preProcess(int [] a, int n)
{
build_spf();
buildSparseTable(a, n);
}
// Driver Code
public static void main(String[] args)
{
int[] arr = { 1, 2, 2, 4, 5 };
int [][]queries = {
{ 2, 3 }, { 2, 4 }, { 3, 4 }, { 4, 4 }, { 4, 5 }
};
preProcess(arr, arr.length);
solveQueries(arr, arr.length, queries);
}
}
// This code is contributed by 29AjayKumar
Python3
# python program for the above approach
import math
MAXN = 200001
# creating 2-D table of size 1001*1001
table = []
for i in range(0, 1001):
table.append([])
for j in range(0, 1001):
table[i].append([])
# Function to build sparse table
def buildSparseTable(arr, n):
# GCD of single element is
# the element itself
for i in range(0, n):
table[i][0] = arr[i]
# Build sparse table
for j in range(1, (int)(math.log2(n))+1):
for i in range(0, n-(1 << j) + 1):
table[i][j] = math.gcd(
table[i][j - 1], table[i + (1 << (j - 1))][j - 1])
# Function to return the GCD of
# all elements in range [L, R]
def find_gcd(L, R):
# Highest power of 2 that is not
# more than count of elements
j = (int)(math.log2(R - L + 1))
# Return GCD in range
return math.gcd(table[L][j],
table[R - (1 << j) + 1][j])
# Smallest prime factors array
spf = [0]*MAXN
# Function to build the smallest
# prime factor array using Sieve
def build_spf():
spf[1] = 1
for i in range(2, MAXN):
spf[i] = i
for i in range(2, MAXN, 2):
spf[i] = 2
for i in range(3, (int)(math.sqrt(MAXN))):
if (spf[i] == i):
for j in range(i*i, MAXN, i):
if (spf[j] == j):
spf[j] = i
# Function to find the count of
# distinct prime factors of x
def getFactorization(x):
# Stores the required count
ctr = 0
while (x != 1):
ctr += 1
# Stores smallest prime
# factor of x
x = (int)(x)
p = spf[x]
while (x % p == 0):
x = x // p
# Return count
return ctr
# Function to count of coprime pairs such
# that the product of the pair divides
# all integers of subarray in given range
def solveQueries(a, n, q):
# Loop to iterate over queries
for i in range(len(q)):
l = q[i][0]
r = q[i][1]
l -= 1
r -= 1
# Stores gcd in the range
gcd = find_gcd(l, r)
# Stores the required count
ans = 0
# Count the pairs of co-primes
# integers in given format
for i in range(1, (int)(math.sqrt(gcd)+1)):
# If i is a factor of gcd
if (gcd % i == 0):
ans = ans + (1 << getFactorization(i))
if (gcd / i != i):
ans += (1
<< getFactorization(gcd / i))
# Print answer
print(ans, end=" ")
# Function to perform precomputation
def preProcess(a, n):
build_spf()
buildSparseTable(a, n)
# Driver Code
arr = [1, 2, 2, 4, 5]
queries = [[2, 4], [2, 4], [3, 4], [4, 4], [4, 5]]
preProcess(arr, len(arr))
solveQueries(arr, len(arr), queries)
# This code is contributed by rj13to.
C#
// C# program for the above approach
using System;
public class GFG{
static readonly int MAXN = 200001;
static int [,]table = new int[1001,1001];
// Function to build sparse table
static void buildSparseTable(int[] arr, int n)
{
// GCD of single element is
// the element itself
for (int i = 0; i < n; i++)
table[i,0] = arr[i];
// Build sparse table
for (int j = 1; j <= Math.Log(n); j++)
for (int i = 0; i <= n - (1 << j);
i++)
table[i,j]
= __gcd(table[i,j - 1],
table[i + (1 << (j - 1)),j - 1]);
}
static int __gcd(int a, int b)
{
return b == 0? a:__gcd(b, a % b);
}
// Function to return the GCD of
// all elements in range [L, R]
static int find_gcd(int L, int R)
{
// Highest power of 2 that is not
// more than count of elements
int j = (int)Math.Log(R - L + 1);
// Return GCD in range
return __gcd(table[L,j],
table[R - (1 << j) + 1,j]);
}
// Smallest prime factors array
static int []spf = new int[MAXN];
// Function to build the smallest
// prime factor array using Sieve
static void build_spf()
{
spf[1] = 1;
for (int i = 2; i < MAXN; i++)
spf[i] = i;
for (int i = 4; i < MAXN; i += 2)
spf[i] = 2;
for (int i = 3; i * i < MAXN; i++) {
if (spf[i] == i) {
for (int j = i * i; j < MAXN;
j += i)
if (spf[j] == j)
spf[j] = i;
}
}
}
// Function to find the count of
// distinct prime factors of x
static int getFactorization(int x)
{
// Stores the required count
int ctr = 0;
while (x != 1) {
ctr++;
// Stores smallest prime
// factor of x
int p = spf[x];
while (x % p == 0)
x = x / p;
}
// Return count
return ctr;
}
// Function to count of coprime pairs such
// that the product of the pair divides
// all integers of subarray in given range
static void solveQueries(int [] a, int n,
int [,] q)
{
// Loop to iterate over queries
for (int i = 0; i < q.GetLength(0); i++) {
int l = q[i,0];
int r = q[i,1];
l--;
r--;
// Stores gcd in the range
int gcd = find_gcd(l, r);
// Stores the required count
int ans = 0;
// Count the pairs of co-primes
// integers in given format
for (int j = 1; j * j <= gcd; j++) {
// If i is a factor of gcd
if (gcd % j == 0) {
ans = ans + (1 << getFactorization(j));
if (gcd / j != j)
ans += (1
<< getFactorization(gcd / j));
}
}
// Print answer
Console.Write(ans+ " ");
}
}
// Function to perform precomputation
static void preProcess(int [] a, int n)
{
build_spf();
buildSparseTable(a, n);
}
// Driver Code
public static void Main(String[] args)
{
int[] arr = { 1, 2, 2, 4, 5 };
int [,]queries = {
{ 2, 3 }, { 2, 4 }, { 3, 4 }, { 4, 4 }, { 4, 5 }
};
preProcess(arr, arr.Length);
solveQueries(arr, arr.Length, queries);
}
}
// This code is contributed by 29AjayKumar
Javascript
3 3 3 5 1
时间复杂度: O(Q * sqrt(M) * log M),其中 M 是给定数组中的最大整数
辅助空间: O(M*log M)