# Queries for Count of divisors of product of an Array in given range | Set 2 (MO’s Algorithm)

Given an array arr of size N and Q queries of the form [L, R], the task is to find the number of divisors of the product of this array in the given range.
Prerequisite: MO’s Algorithm, Modular Multiplicative Inverse, Prime Factorization using sieve
Examples:

Input: arr[] = {4, 1, 9, 12, 5, 3}, Q = {{1, 3}, {3, 5}}
Output:

24
Input: arr[] = {5, 2, 3, 1, 4}, Q = {{2, 4}, {1, 5}}
Output:

16

Approach:
The idea of MOâ€™s algorithm is to pre-process all queries so that result of one query can be used in the next query.
Let a[0â€¦n-1] be input array and q[0..m-1] be an array of queries.

1. Sort all queries in a way that queries with L values from 0 to ?n â€“ 1 are put together, then all queries from ?n to 2Ã—?n â€“ 1, and so on. All queries within a block are sorted in increasing order of R values.

2. Process all queries one by one in a way that every query uses result computed in the previous query. Let ‘result’ be result of previous query

3. A number n can be represented as n =
```*** QuickLaTeX cannot compile formula:

*** Error message:
Error: Nothing to show, formula is empty
```

, where ai are prime factors and pi are integral power of them.
So, for this factorization we have formula to find total number of divisor of n and that is:

1. In Add function we increment counter array as i.e counter[a[i]]=counter[a[i]]+ pi. Let ‘prev’ stores the previous value of counter[a[i]]. Now as counter array changes, result changes as:

• result = result / (prev + 1) (Dividing by prev+1 neutralizes the effect of previous pi

• result = (result Ã— (counter[pi] + 1) (Now the previous result is neutralized so we multiply with the new count i.e counter[a[i]]+1)

1.
2. In Remove function we decrement the counter array as counter[a[i]] = counter[a[i]] – pi. Now as counter array changes, result changes as:

• result = result / (prev + 1) (Dividing by prev+1 neutralizes the effect of previous pi

• result = (result Ã— (counter[pi] + 1) (Now the previous result is neutralized so we
multiply with the new count i.e counter[a[i]]+1)

1.

Below is the implementation of the above approach

## CPP

 `// C++ program to Count the divisors ` `// of product of an Array in range ` `// L to R for Q queries` `#include ` `using` `namespace` `std;`   `#define MAX 1000000` `#define MOD 1000000007` `#define ll long long int`   `// Variable to represent block size.` `// This is made global so compare()` `// of sort can use it.` `int` `block;`   `// Structure to represent a query range` `struct` `Query {` `    ``int` `L, R;` `};`   `// Store the prime factor of numbers` `// till MAX` `vector > store[MAX + 1];`   `// Initialized to store the count ` `// of prime factors` `int` `counter[MAX + 1] = {};`   `// Result is Initialized to 1` `int` `result = 1;`   `// Inverse array to store` `// inverse of number from 1 to MAX` `ll inverse[MAX + 1];`   `// Function used to sort all queries so that ` `// all queries of the same block are arranged ` `// together and within a block, queries are` `// sorted in increasing order of R values.` `bool` `compare(Query x, Query y)` `{` `    ``// Different blocks, sort by block.` `    ``if` `(x.L / block != y.L / block)` `        ``return` `x.L / block < y.L / block;`   `    ``// Same block, sort by R value` `    ``return` `x.R < y.R;` `}`   `// Function to calculate modular` `// inverse and storing it in Inverse array` `void` `modularInverse()` `{`   `    ``inverse[0] = inverse[1] = 1;` `    ``for` `(``int` `i = 2; i <= MAX; i++)` `        ``inverse[i] = inverse[MOD % i]` `                    ``* (MOD - MOD / i) ` `                      ``% MOD;` `}`   `// Function to use Sieve to compute` `// and store prime numbers` `void` `sieve()` `{`   `    ``store[1].push_back({ 1, 0 });` `    ``for` `(``int` `i = 2; i <= MAX; i++)` `    ``{` `        ``if` `(store[i].size() == 0)` `        ``{` `            ``store[i].push_back({ i, 1 });` `            `  `            ``for` `(``int` `j = 2 * i; j <= MAX; j += i)` `            ``{` `                ``int` `cnt = 0;` `                ``int` `x = j;` `                ``while` `(x % i == 0)` `                    ``cnt++, x /= i;` `                ``store[j].push_back({ i, cnt });` `            ``}` `        ``}` `    ``}` `}`   `// Function to Add elements` `// of current range` `void` `add(``int` `currL, ``int` `a[])` `{` `    ``int` `value = a[currL];` `    ``for` `(``auto` `it = store[value].begin();` `         ``it != store[value].end(); it++) {` `        ``// it->first is ai` `        ``// it->second is its integral power` `        ``int` `prev = counter[it->first];` `        ``counter[it->first] += it->second;` `        ``result = (result * inverse[prev + 1])` `                 ``% MOD;` `        `  `        ``result = (result *` `                  ``(counter[it->first] + 1))` `                  ``% MOD;` `    ``}` `}`   `// Function to remove elements` `// of previous range` `void` `remove``(``int` `currR, ``int` `a[])` `{` `    ``int` `value = a[currR];` `    ``for` `(``auto` `it = store[value].begin(); ` `         ``it != store[value].end(); it++) {` `        ``// it->first is ai` `        ``// it->second is its integral power` `        ``int` `prev = counter[it->first];` `        ``counter[it->first] -= it->second;` `        ``result = (result * inverse[prev + 1])` `                  ``% MOD;` `        ``result = (result *` `                  ``(counter[it->first] + 1)) ` `                  ``% MOD;` `    ``}` `}`   `// Function to print the answer.` `void` `queryResults(``int` `a[], ``int` `n, Query q[],` `                  ``int` `m)` `{` `    ``// Find block size` `    ``block = (``int``)``sqrt``(n);`   `    ``// Sort all queries so that queries of ` `    ``// same blocks are arranged together.` `    ``sort(q, q + m, compare);`   `    ``// Initialize current L, current R and` `    ``// current result` `    ``int` `currL = 0, currR = 0;`   `    ``for` `(``int` `i = 0; i < m; i++) {` `        ``// L and R values of current range` `        ``int` `L = q[i].L, R = q[i].R;`   `        ``// Add Elements of current range` `        ``while` `(currR <= R) {` `            ``add(currR, a);` `            ``currR++;` `        ``}` `        ``while` `(currL > L) {` `            ``add(currL - 1, a);` `            ``currL--;` `        ``}`   `        ``// Remove element of previous range` `        ``while` `(currR > R + 1)`   `        ``{` `            ``remove``(currR - 1, a);` `            ``currR--;` `        ``}` `        ``while` `(currL < L) {` `            ``remove``(currL, a);` `            ``currL++;` `        ``}`   `        ``cout << result << endl;` `    ``}` `}`   `// Driver Code` `int` `main()` `{` `    ``// Precomputing the prime numbers ` `    ``// using sieve` `    ``sieve();`   `    ``// Precomputing modular inverse of ` `    ``// numbers from 1 to MAX` `    ``modularInverse();`   `    ``int` `a[] = { 5, 2, 3, 1, 4 };` `    ``int` `n = ``sizeof``(a) / ``sizeof``(a[0]);` `    `  `    ``Query q[] = { { 1, 3 }, { 0, 4 } };` `    `  `    ``int` `m = ``sizeof``(q) / ``sizeof``(q[0]);` `    `  `    ``// Answer the queries` `    ``queryResults(a, n, q, m);` `    ``return` `0;` `}`

Output:

```4
16```

Time Complexity: O(QÃ—sqrt(N))
Auxiliary Space: O(MAX) where MAX=1000000

Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!

Previous
Next