Open In App

Prime Range Query

Last Updated : 11 Dec, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an array of integers A[] and a list of queries Q[]. Each query specifies a range [L, R] (1-based indices) in the array.
For each query, our task is to determine how many prime numbers divide every element in the subarray A[L] to A[R] inclusive.

Examples:

Input: A[] = [2, 4, 6, 1, 9], Q[] = [[1, 5], [3, 3], [2, 3]]
Output: [0, 2, 1]
Explanation:
In query 1 ,there is no prime number which divides all the numbers from indices 1 to 5.
In query 2, there are two prime number (2, 3)
In query 3, there is only one prime number (2)

Input: A[] = [15, 30, 45, 10, 20], Q[] = [[1, 3], [2, 5], [4, 5], [1, 5]]
Output: [2, 1, 2, 0]
Explanation:
In query 1, there are two prime numbers (3, 5) which divide all numbers from indices 1 to 3.
In query 2, there is only one prime number (2) which divides all numbers from indices 2 to 5.
In query 3, there are two prime numbers (2, 5) which divide all numbers from indices 4 to 5.
In query 4, there is no prime number which divides all numbers from indices 1 to 5.

[ Approach 1] Count Prime Divisors Using GCD- O(q x (n + sqrt(max(A)))) Time and O(q) Space

The idea is we can use the concept of the greatest common divisor (GCD). For each query, which specifies a range in the array, the prime numbers that divide every element in that subarray are exactly the prime factors of the GCD of the subarray. In other words, instead of checking each prime for every number in the range, we first compute the GCD of all numbers between indices L and R. Once we have the GCD, we factorize it and count the number of distinct prime numbers that divide it. This count gives the answer for the query

C++
#include <iostream>
#include <vector>
using namespace std;

// Function to compute GCD of two numbers
int gcdVal(int a, int b) {
    while (b != 0) {
        int temp = a % b;
        a = b;
        b = temp;
    }
    return a;
}

// Function to count distinct prime factors of a number
int countPrimeFactors(int x) {
    int count = 0;

    // factor 2
    if (x % 2 == 0) {
        count++;
        while (x % 2 == 0) x /= 2;
    }

    // odd factors
    for (int i = 3; i * i <= x; i += 2) {
        if (x % i == 0) {
            count++;
            while (x % i == 0) x /= i;
        }
    }

    // leftover prime
    if (x > 1) count++;

    return count;
}

// Main solve function
vector<int> solve(vector<int> A, vector<vector<int>> Q) {

    vector<int> ans;
    int n=A.size();
    int q=Q.size();
    // Process each query
    for (int k = 0; k < q; k++) {

        int L = Q[k][0];
        int R = Q[k][1];

        // Compute GCD of range [L, R]
        int g = A[L - 1];
        for (int i = L; i < R; i++) {
            g = gcdVal(g, A[i]);
        }

        // Count prime numbers dividing this GCD
        int cnt = countPrimeFactors(g);

        ans.push_back(cnt);
    }

    return ans;
}

int main() {

    vector<int> A = {2, 4, 6, 1, 9};

    vector<vector<int>> Q = {
        {1, 5},
        {3, 3},
        {2, 3}
    };

    // Call solve function
    vector<int> result = solve(A, Q);

    // Output the results
    for (int i = 0; i < result.size(); i++) {
        cout << result[i] << " ";
    }

    return 0;
}
Java
import java.util.ArrayList;

class GFG {

    // Function to compute GCD of two numbers
    static int gcdVal(int a, int b) {
        while (b != 0) {
            int temp = a % b;
            a = b;
            b = temp;
        }
        return a;
    }

    // Function to count distinct prime factors of a number
    static int countPrimeFactors(int x) {
        int count = 0;

        // factor 2
        if (x % 2 == 0) {
            count++;
            while (x % 2 == 0) x /= 2;
        }

        // odd factors
        for (int i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                count++;
                while (x % i == 0) x /= i;
            }
        }

        // leftover prime
        if (x > 1) count++;

        return count;
    }

    // Main solve function
    static ArrayList<Integer> solve(int[] A, int[][] Q) {

        ArrayList<Integer> ans = new ArrayList<>();
        int n = A.length;
        int q = Q.length;

        // Process each query
        for (int k = 0; k < q; k++) {

            int L = Q[k][0];
            int R = Q[k][1];

            // Compute GCD of range [L, R]
            int g = A[L - 1];
            for (int i = L; i < R; i++) {
                g = gcdVal(g, A[i]);
            }

            // Count prime numbers dividing this GCD
            int cnt = countPrimeFactors(g);

            ans.add(cnt);
        }

        return ans;
    }

    public static void main(String[] args) {

        int[] A = {2, 4, 6, 1, 9};

        int[][] Q = {
            {1, 5},
            {3, 3},
            {2, 3}
        };

        ArrayList<Integer> result = solve(A, Q);

        for (int v : result) {
            System.out.print(v + " ");
        }
    }
}
Python
# Function to compute GCD of two numbers
def gcdVal(a, b):
    while b != 0:
        temp = a % b
        a = b
        b = temp
    return a

# Function to count distinct prime factors of a number
def countPrimeFactors(x):
    count = 0

    # factor 2
    if x % 2 == 0:
        count += 1
        while x % 2 == 0:
            x //= 2

    # odd factors
    i = 3
    while i * i <= x:
        if x % i == 0:
            count += 1
            while x % i == 0:
                x //= i
        i += 2

    # leftover prime
    if x > 1:
        count += 1

    return count


def solve(A, Q):
    ans = []
    n = len(A)
    q = len(Q)

    # Process each query
    for L, R in Q:

        # Compute GCD of range [L, R]
        g = A[L - 1]
        for i in range(L, R):
            g = gcdVal(g, A[i])

        # Count prime numbers dividing this GCD
        cnt = countPrimeFactors(g)
        ans.append(cnt)

    return ans

if __name__ == "__main__":
    A = [2, 4, 6, 1, 9]
    Q = [(1, 5), (3, 3), (2, 3)]
    
    print(solve(A, Q))
C#
using System;
using System.Collections.Generic;

class GFG {

    // Function to compute GCD of two numbers
    static int gcdVal(int a, int b) {
        while (b != 0) {
            int temp = a % b;
            a = b;
            b = temp;
        }
        return a;
    }

    // Function to count distinct prime factors of a number
    static int countPrimeFactors(int x) {
        int count = 0;

        // factor 2
        if (x % 2 == 0) {
            count++;
            while (x % 2 == 0) x /= 2;
        }

        // odd factors
        for (int i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                count++;
                while (x % i == 0) x /= i;
            }
        }

        // leftover prime
        if (x > 1) count++;

        return count;
    }

    // Main solve function
    static List<int> solve(int[] A, int[,] Q) {

        List<int> ans = new List<int>();

        int q = Q.GetLength(0);

        // Process each query
        for (int k = 0; k < q; k++) {

            int L = Q[k, 0];
            int R = Q[k, 1];

            // Compute GCD of range [L, R]
            int g = A[L - 1];
            for (int i = L; i < R; i++) {
                g = gcdVal(g, A[i]);
            }

            // Count prime numbers dividing this GCD
            ans.Add(countPrimeFactors(g));
        }

        return ans;
    }

    static void Main() {

        int[] A = {2, 4, 6, 1, 9};

        int[,] Q = {
            {1, 5},
            {3, 3},
            {2, 3}
        };

        var result = solve(A, Q);

        foreach (int v in result)
            Console.Write(v + " ");
    }
}
JavaScript
// Function to compute GCD of two numbers
function gcdVal(a, b) {
    while (b !== 0) {
        let temp = a % b;
        a = b;
        b = temp;
    }
    return a;
}

// Function to count distinct prime factors of a number
function countPrimeFactors(x) {
    let count = 0;

    // factor 2
    if (x % 2 === 0) {
        count++;
        while (x % 2 === 0) x /= 2;
    }

    // odd factors
    for (let i = 3; i * i <= x; i += 2) {
        if (x % i === 0) {
            count++;
            while (x % i === 0) x /= i;
        }
    }

    // leftover prime
    if (x > 1) count++;

    return count;
}

// Main solve function
function solve(A, Q) {
    let ans = [];

    // Process each query
    for (let k = 0; k < Q.length; k++) {

        let L = Q[k][0];
        let R = Q[k][1];

        // Compute GCD of range [L, R]
        let g = A[L - 1];
        for (let i = L; i < R; i++) {
            g = gcdVal(g, A[i]);
        }

        // Count prime numbers dividing this GCD
        ans.push(countPrimeFactors(g));
    }

    return ans;
}

//Driver Code
let A = [2, 4, 6, 1, 9];
let Q = [[1,5], [3,3], [2,3]];

console.log(solve(A, Q));

Output
0 2 1 

[Optimal Approach] Segment Tree with Prime Factorization - O(n + q x (log n + sqrt(max(A)))) Time and O(n + q) Space

To optimize the solution, we preprocess the array using a Segment Tree. Each node of the tree stores the distinct prime factors of the GCD of its corresponding segment. This allows us to combine information efficiently. For any query [L,R], we traverse the Segment Tree and quickly obtain the GCD’s prime factors for that range without recalculating from scratch. Once we get the set of prime factors for the queried segment, we simply count how many distinct prime numbers divide the entire subarray. This reduces repeated work and makes the processing of multiple queries significantly faster.

C++
#include <iostream>
#include <vector>
using namespace std;

    // Function to compute GCD of two numbers
    int gcd(int a, int b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    // Function to count distinct prime factors of a number
    int countPrimeFactors(int x) {
        if (x <= 1) return 0;

        int count = 0;
        for (int i = 2; i * i <= x; i++) {
            if (x % i == 0) {
                count++;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) count++;
        return count;
    }

    // Build segment tree storing GCD for each segment
    void buildGCDTree(vector<int>& A, vector<int>& seg, int node, int start, int end) {
        if (start == end) {
            seg[node] = A[start];
        } else {
            int mid = (start + end) / 2;
            buildGCDTree(A, seg, 2 * node + 1, start, mid);
            buildGCDTree(A, seg, 2 * node + 2, mid + 1, end);
            seg[node] = gcd(seg[2 * node + 1], seg[2 * node + 2]);
        }
    }

    // Query GCD for range [L, R] in segment tree
    int queryGCD(vector<int>& seg, int node, int start, int end, int L, int R) {
        
        // No overlap
        if (R < start || end < L) return 0;
        
        // Complete overlap
        if (L <= start && end <= R) return seg[node];
        
        // Partial overlap
        int mid = (start + end) / 2;
        int leftGCD = queryGCD(seg, 2 * node + 1, start, mid, L, R);
        int rightGCD = queryGCD(seg, 2 * node + 2, mid + 1, end, L, R);
        return gcd(leftGCD, rightGCD);
    }

    vector<int> solve(vector<int>&A, vector<vector<int>> Q) {
        int n= A.size();
        int q=Q.size();
        vector<int> ans;
         // Segment Tree
        vector<int> seg(4 * n);

        // Build the segment tree
        buildGCDTree(A, seg, 0, 0, n - 1);

        // Process each query
        for (int k = 0; k < q; k++) {
            
             // Convert to 0-based index
            int L = Q[k][0] - 1;
            int R = Q[k][1] - 1;
            
            // Get GCD of range
            int rangeGCD = queryGCD(seg, 0, 0, n- 1, L, R); 
            
            // Count prime factors of GCD
            int count = countPrimeFactors(rangeGCD); 
            ans.push_back(count);
        }

        return ans;
    }

int main() {
    vector<int> A = {2, 4, 6, 1, 9};
    vector<vector<int>> Q = {
        {1, 5},
        {3, 3},
        {2, 3}
    };

    vector<int> result = solve(A, Q);

    for (int x : result) {
        cout << x << " ";
    }

    return 0;
}
Java
import java.util.ArrayList;

class GFG {

    // Function to compute GCD of two numbers
    static int gcd(int a, int b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    // Function to count distinct prime factors of a number
    static int countPrimeFactors(int x) {
        if (x <= 1) return 0;

        int count = 0;
        for (int i = 2; i * i <= x; i++) {
            if (x % i == 0) {
                count++;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) count++;
        return count;
    }

    // Build segment tree storing GCD for each segment
    static void buildGCDTree(int[] A, int[] seg, int node, int start, int end) {
        if (start == end) {
            seg[node] = A[start];
        } else {
            int mid = (start + end) / 2;
            buildGCDTree(A, seg, 2 * node + 1, start, mid);
            buildGCDTree(A, seg, 2 * node + 2, mid + 1, end);
            seg[node] = gcd(seg[2 * node + 1], seg[2 * node + 2]);
        }
    }

    // Query GCD for range [L, R] in segment tree
    static int queryGCD(int[] seg, int node, int start, int end, int L, int R) {

        // No overlap
        if (R < start || end < L) return 0;

        // Complete overlap
        if (L <= start && end <= R) return seg[node];

        // Partial overlap
        int mid = (start + end) / 2;
        int leftGCD = queryGCD(seg, 2 * node + 1, start, mid, L, R);
        int rightGCD = queryGCD(seg, 2 * node + 2, mid + 1, end, L, R);

        return gcd(leftGCD, rightGCD);
    }

    static ArrayList<Integer> solve(int[] A, int[][] Q) {
        int n = A.length;
        int q = Q.length;

        ArrayList<Integer> ans = new ArrayList<>();

        // Segment Tree
        int[] seg = new int[4 * n];

        // Build the segment tree
        buildGCDTree(A, seg, 0, 0, n - 1);

        // Process each query
        for (int k = 0; k < q; k++) {

            int L = Q[k][0] - 1;
            int R = Q[k][1] - 1;

            // Get GCD of range
            int rangeGCD = queryGCD(seg, 0, 0, n - 1, L, R);

            // Count prime factors
            ans.add(countPrimeFactors(rangeGCD));
        }

        return ans;
    }

    public static void main(String[] args) {

        int[] A = {2, 4, 6, 1, 9};

        int[][] Q = {
            {1, 5},
            {3, 3},
            {2, 3}
        };

        ArrayList<Integer> result = solve(A, Q);

        for (int x : result) {
            System.out.print(x + " ");
        }
    }
}
Python
# Function to compute GCD of two numbers
def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a % b)

# Function to count distinct prime factors of a number
def countPrimeFactors(x):
    if x <= 1:
        return 0

    count = 0
    i = 2
    while i * i <= x:
        if x % i == 0:
            count += 1
            while x % i == 0:
                x //= i
        i += 1

    if x > 1:
        count += 1

    return count

# Build segment tree storing GCD for each segment
def buildGCDTree(A, seg, node, start, end):
    if start == end:
        seg[node] = A[start]
    else:
        mid = (start + end) // 2
        buildGCDTree(A, seg, 2 * node + 1, start, mid)
        buildGCDTree(A, seg, 2 * node + 2, mid + 1, end)
        seg[node] = gcd(seg[2 * node + 1], seg[2 * node + 2])

# Query GCD for range [L, R] in segment tree
def queryGCD(seg, node, start, end, L, R):

    # No overlap
    if R < start or end < L:
        return 0

    # Complete overlap
    if L <= start and end <= R:
        return seg[node]

    # Partial overlap
    mid = (start + end) // 2
    leftGCD = queryGCD(seg, 2 * node + 1, start, mid, L, R)
    rightGCD = queryGCD(seg, 2 * node + 2, mid + 1, end, L, R)

    return gcd(leftGCD, rightGCD)

def solve(A, Q):
    n = len(A)
    ans = []

    # Segment Tree
    seg = [0] * (4 * n)

    # Build the segment tree
    buildGCDTree(A, seg, 0, 0, n - 1)

    # Process queries
    for L, R in Q:

        L -= 1
        R -= 1

        rangeGCD = queryGCD(seg, 0, 0, n - 1, L, R)

        ans.append(countPrimeFactors(rangeGCD))

    return ans


if __name__ == "__main__":
    A = [2, 4, 6, 1, 9]
    Q = [[1, 5], [3, 3], [2, 3]]
    
    print(solve(A, Q))
C#
using System;

class GFG
{
    // Function to compute GCD of two numbers
    static int gcd(int a, int b)
    {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    // Function to count distinct prime factors of a number
    static int countPrimeFactors(int x)
    {
        if (x <= 1) return 0;

        int count = 0;
        for (int i = 2; i * i <= x; i++)
        {
            if (x % i == 0)
            {
                count++;
                while (x % i == 0)
                {
                    x /= i;
                }
            }
        }
        if (x > 1) count++;

        return count;
    }

    // Build segment tree storing GCD for each segment
    static void buildGCDTree(int[] A, int[] seg, int node, int start, int end)
    {
        if (start == end)
        {
            seg[node] = A[start];
        }
        else
        {
            int mid = (start + end) / 2;
            buildGCDTree(A, seg, 2 * node + 1, start, mid);
            buildGCDTree(A, seg, 2 * node + 2, mid + 1, end);
            seg[node] = gcd(seg[2 * node + 1], seg[2 * node + 2]);
        }
    }

    // Query GCD for range [L, R] in segment tree
    static int queryGCD(int[] seg, int node, int start, int end, int L, int R)
    {
        // No overlap
        if (R < start || end < L) return 0;

        // Complete overlap
        if (L <= start && end <= R) return seg[node];

        // Partial overlap
        int mid = (start + end) / 2;
        int leftGCD = queryGCD(seg, 2 * node + 1, start, mid, L, R);
        int rightGCD = queryGCD(seg, 2 * node + 2, mid + 1, end, L, R);

        return gcd(leftGCD, rightGCD);
    }

    static int[] solve(int[] A, int[,] Q)
    {
        int n = A.Length;
        int q = Q.GetLength(0);
        int[] ans = new int[q];

        // Segment Tree
        int[] seg = new int[4 * n];

        // Build the segment tree
        buildGCDTree(A, seg, 0, 0, n - 1);

        // Process each query
        for (int k = 0; k < q; k++)
        {
            // Convert to 0-based index
            int L = Q[k, 0] - 1;
            int R = Q[k, 1] - 1;

            // Get GCD of range
            int rangeGCD = queryGCD(seg, 0, 0, n - 1, L, R);

            // Count prime factors of GCD
            ans[k] = countPrimeFactors(rangeGCD);
        }

        return ans;
    }

    static void Main()
    {
        int[] A = { 2, 4, 6, 1, 9 };

        int[,] Q =
        {
            { 1, 5 },
            { 3, 3 },
            { 2, 3 }
        };

        int[] result = solve(A, Q);

        foreach (int x in result)
        {
            Console.Write(x + " ");
        }
    }
}
JavaScript
// Function to compute GCD of two numbers
function gcd(a, b) {
    if (b === 0) return a;
    return gcd(b, a % b);
}

// Function to count distinct prime factors of a number
function countPrimeFactors(x) {
    if (x <= 1) return 0;

    let count = 0;
    for (let i = 2; i * i <= x; i++) {
        if (x % i === 0) {
            count++;
            while (x % i === 0) x = Math.floor(x / i);
        }
    }
    if (x > 1) count++;
    return count;
}

// Build segment tree storing GCD for each segment
function buildGCDTree(A, seg, node, start, end) {
    if (start === end) {
        seg[node] = A[start];
    } else {
        let mid = Math.floor((start + end) / 2);
        buildGCDTree(A, seg, 2 * node + 1, start, mid);
        buildGCDTree(A, seg, 2 * node + 2, mid + 1, end);
        seg[node] = gcd(seg[2 * node + 1], seg[2 * node + 2]);
    }
}

// Query GCD for range [L, R] in segment tree
function queryGCD(seg, node, start, end, L, R) {

    // No overlap
    if (R < start || end < L) return 0;

    // Complete overlap
    if (L <= start && end <= R) return seg[node];

    // Partial overlap
    let mid = Math.floor((start + end) / 2);
    let leftGCD = queryGCD(seg, 2 * node + 1, start, mid, L, R);
    let rightGCD = queryGCD(seg, 2 * node + 2, mid + 1, end, L, R);
    return gcd(leftGCD, rightGCD);
}

function solve(A, Q) {
    let n = A.length;
    let q = Q.length;
    let ans = [];

    // Segment Tree
    let seg = new Array(4 * n);

    // Build the segment tree
    buildGCDTree(A, seg, 0, 0, n - 1);

    // Process each query
    for (let k = 0; k < q; k++) {

        // Convert to 0-based index
        let L = Q[k][0] - 1;
        let R = Q[k][1] - 1;

        // Get GCD of range
        let rangeGCD = queryGCD(seg, 0, 0, n - 1, L, R);

        // Count prime factors of GCD
        let count = countPrimeFactors(rangeGCD);
        ans.push(count);
    }

    return ans;
}

// Driver Code
let A = [2, 4, 6, 1, 9];
let Q = [
    [1, 5],
    [3, 3],
    [2, 3]
];

let result = solve(A, Q);

console.log(result.join(" "));

Output
0 2 1 



Article Tags :

Explore