📌  相关文章
📜  对于 Q 查询,不同互质对乘积除以索引 [L, R] 中的所有元素的计数

📅  最后修改于: 2022-05-13 01:56:05.668000             🧑  作者: Mango

对于 Q 查询,不同互质对乘积除以索引 [L, R] 中的所有元素的计数

给定一个包含N个整数的数组arr[](l, r)形式的Q个查询。任务是为每个查询找到不同的互素整数对的数量,使得索引范围[l, r]中的所有整数都可以被互素整数的乘积整除。

例子:

方法:给定的问题可以在稀疏表的帮助下得到最佳解决。该方法基于这样一个事实,即只有子阵列的 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)