 GFG App
Open App Browser
Continue

# Range Queries for count of Armstrong numbers in subarray using MO’s algorithm

Given an array arr[] consisting of N elements and Q queries represented by L and R denoting a range, the task is to print the number of Armstrong numbers in the subarray [L, R].

Examples:

Input: arr[] = {18, 153, 8, 9, 14, 5}
Query 1: query(L=0, R=5)
Query 2: query(L=3, R=5)
Output:

Explanation:
18 => 1*1 + 8*8 != 18
153 => 1*1*1 + 5*5*5 + 3*3*3 = 153
8 => 8 = 8
9 => 9 = 9
14 => 1*1 + 4*4 != 14
Query 1: The subarray[0…5] has 4 Armstrong numbers viz. {153, 8, 9, 5}
Query 2: The subarray[3…5] has 2 Armstrong numbers viz. {9, 5}

Approach:
The idea is to use MO’s algorithm to pre-process all queries so that result of one query can be used in the next query.

1. Sort all queries in a way that queries with L values from 0 to √n – 1 are put together, followed by 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 and increase the count of Armstrong numbers and store the result in the structure.
• Let ‘count_Armstrong‘ store the count of Armstrong numbers in the previous query.
• Remove extra elements of previous query and add new elements for the current query. For example, if previous query was [0, 8] and the current query is [3, 9], then remove the elements arr, arr and arr and add arr.
3. In order to display the results, sort the queries in the order they were provided.

• If the current element is a Armstrong number then increment count_Armstrong.

Removing elements

• If the current element is a Armstrong number then decrement count_Armstrong.

Below is the implementation of the above approach:

## C++

 `// C++ implementation to count the` `// number of Armstrong numbers` `// in subarray using MO’s algorithm`   `#include ` `using` `namespace` `std;`   `// 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, index;`   `    ``// Count of Armstrong` `    ``// numbers` `    ``int` `armstrong;` `};`   `// To store the count of` `// Armstrong numbers` `int` `count_Armstrong;`   `// 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 used to sort all` `// queries in order of their` `// index value so that results` `// of queries can be printed` `// in same order as of input` `bool` `compare1(Query x, Query y)` `{` `    ``return` `x.index < y.index;` `}`   `// Function that return true` `// if num is armstrong` `// else return false` `bool` `isArmstrong(``int` `x)` `{` `    ``int` `n = to_string(x).size();` `    ``int` `sum1 = 0;` `    ``int` `temp = x;` `    ``while` `(temp > 0) {` `        ``int` `digit = temp % 10;` `        ``sum1 += ``pow``(digit, n);` `        ``temp /= 10;` `    ``}` `    ``if` `(sum1 == x)` `        ``return` `true``;` `    ``return` `false``;` `}`   `// Function to Add elements` `// of current range` `void` `add(``int` `currL, ``int` `a[])` `{` `    ``// If a[currL] is a Armstrong number` `    ``// then increment count_Armstrong` `    ``if` `(isArmstrong(a[currL]))` `        ``count_Armstrong++;` `}`   `// Function to remove elements` `// of previous range` `void` `remove``(``int` `currR, ``int` `a[])` `{` `    ``// If a[currL] is a Armstrong number` `    ``// then decrement count_Armstrong` `    ``if` `(isArmstrong(a[currR]))` `        ``count_Armstrong--;` `}`   `// Function to generate the result of queries` `void` `queryResults(``int` `a[], ``int` `n, Query q[],` `                  ``int` `m)` `{`   `    ``// Initialize count_Armstrong to 0` `    ``count_Armstrong = 0;`   `    ``// 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++;` `        ``}`   `        ``q[i].armstrong = count_Armstrong;` `    ``}` `}`   `// Function to display the results of` `// queries in their initial order` `void` `printResults(Query q[], ``int` `m)` `{` `    ``sort(q, q + m, compare1);` `    ``for` `(``int` `i = 0; i < m; i++) {` `        ``cout << q[i].armstrong << endl;` `    ``}` `}`   `// Driver Code` `int` `main()` `{`   `    ``int` `arr[] = { 18, 153, 8, 9, 14, 5 };` `    ``int` `n = ``sizeof``(arr) / ``sizeof``(arr);`   `    ``Query q[] = { { 0, 5, 0, 0 },` `                  ``{ 3, 5, 1, 0 } };`   `    ``int` `m = ``sizeof``(q) / ``sizeof``(q);`   `    ``queryResults(arr, n, q, m);`   `    ``printResults(q, m);`   `    ``return` `0;` `}`

## Java

 `// Java implementation to count the ` `// number of Armstrong numbers ` `// in subarray using MO’s algorithm ` `import` `java.io.*;` `import` `java.util.*;`   `// Class to represent` `// a query range` `class` `Query` `{` `    ``int` `L, R, index;`   `    ``// Count of Armstrong` `    ``// numbers` `    ``int` `armstrong;`   `    ``Query(``int` `L, ``int` `R, ``int` `index,` `          ``int` `armstrong)` `    ``{` `        ``this``.L = L;` `        ``this``.R = R;` `        ``this``.index = index;` `        ``this``.armstrong = armstrong;` `    ``}` `}`   `class` `GFG{` `    `  `// Variable to represent block size.` `static` `int` `block;`   `// To store the count of` `// Armstrong numbers` `static` `int` `count_Armstrong;`   `// Function that return true` `// if num is armstrong` `// else return false` `static` `boolean` `isArmstrong(``int` `x)` `{` `    ``int` `n = String.valueOf(x).length();` `    ``int` `sum1 = ``0``;` `    ``int` `temp = x;` `    `  `    ``while` `(temp > ``0``)` `    ``{` `        ``int` `digit = temp % ``10``;` `        ``sum1 += Math.pow(digit, n);` `        ``temp /= ``10``;` `    ``}` `    `  `    ``if` `(sum1 == x)` `        ``return` `true``;`   `    ``return` `false``;` `}`   `// Function to Add elements` `// of current range` `static` `void` `add(``int` `currL, ``int` `a[])` `{` `    `  `    ``// If a[currL] is a Armstrong number` `    ``// then increment count_Armstrong` `    ``if` `(isArmstrong(a[currL]))` `        ``count_Armstrong++;` `}`   `// Function to remove elements` `// of previous range` `static` `void` `remove(``int` `currR, ``int` `a[])` `{` `    `  `    ``// If a[currL] is a Armstrong number` `    ``// then decrement count_Armstrong` `    ``if` `(isArmstrong(a[currR]))` `        ``count_Armstrong--;` `}`   `// Function to generate the result of queries` `static` `void` `queryResults(``int` `a[], ``int` `n, Query q[],` `                         ``int` `m)` `{` `    `  `    ``// Initialize count_Armstrong to 0` `    ``count_Armstrong = ``0``;`   `    ``// Find block size` `    ``block = (``int``)(Math.sqrt(n));`   `    ``// 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.` `    ``Arrays.sort(q, (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;` `    ``});`   `    ``// 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++;` `        ``}`   `        ``q[i].armstrong = count_Armstrong;` `    ``}` `}`   `// Function to display the results of` `// queries in their initial order` `static` `void` `printResults(Query q[], ``int` `m)` `{` `    ``Arrays.sort(q, (Query x, Query y) ->` `    `  `                ``// sort all queries` `                ``// in order of their` `                ``// index value so that results` `                ``// of queries can be printed` `                ``// in same order as of input);` `                ``x.index - y.index);`   `    ``for``(``int` `i = ``0``; i < m; i++) ` `    ``{` `        ``System.out.println(q[i].armstrong);` `    ``}` `}`   `// Driver Code` `public` `static` `void` `main(String[] args)` `{` `    ``int` `arr[] = { ``18``, ``153``, ``8``, ``9``, ``14``, ``5` `};` `    ``int` `n = arr.length;`   `    ``Query q[] = ``new` `Query[``2``];` `    ``q[``0``] = ``new` `Query(``0``, ``5``, ``0``, ``0``);` `    ``q[``1``] = ``new` `Query(``3``, ``5``, ``1``, ``0``);`   `    ``int` `m = q.length;`   `    ``queryResults(arr, n, q, m);`   `    ``printResults(q, m);` `}` `}`   `// This code is contributed by jithin`

## Python3

 `import` `math`   `block ``=` `0` `# Structure to represent a query range` `class` `Query:` `    ``def` `__init__(``self``, L, R, index):` `        ``self``.L ``=` `L` `        ``self``.R ``=` `R` `        ``self``.index ``=` `index` `        ``self``.armstrong ``=` `0`   `# To store the count of Armstrong numbers` `count_Armstrong ``=` `0`   `# 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.` `def` `compare(x, 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 used to sort all` `# queries in order of their` `# index value so that results` `# of queries can be printed` `# in the same order as input` `def` `compare1(x, y):` `    ``return` `x.index < y.index`     `# Function that returns True` `# if num is an Armstrong number` `# else returns False` `def` `isArmstrong(x):` `    ``n ``=` `len``(``str``(x))` `    ``sum1 ``=` `0` `    ``temp ``=` `x` `    ``while` `temp > ``0``:` `        ``digit ``=` `temp ``%` `10` `        ``sum1 ``+``=` `pow``(digit, n)` `        ``temp ``/``/``=` `10` `    ``if` `sum1 ``=``=` `x:` `        ``return` `True` `    ``return` `False`   `# Function to add elements of current range` `def` `add(currL, a):` `    ``global` `count_Armstrong` `    ``# If a[currL] is an Armstrong number,` `    ``# then increment count_Armstrong` `    ``if` `isArmstrong(a[currL]):` `        ``count_Armstrong ``+``=` `1`   `# Function to remove elements of previous range` `def` `remove(currR, a):` `    ``global` `count_Armstrong` `    ``# If a[currL] is an Armstrong number,` `    ``# then decrement count_Armstrong` `    ``if` `isArmstrong(a[currR]):` `        ``count_Armstrong ``-``=` `1`   `def` `queryResults(a, n, q, m):` `    ``global` `block` `    ``global` `count_Armstrong` `    ``# Initialize count_Armstrong to 0` `    ``count_Armstrong ``=` `0`   `    ``block ``=` `int``(math.sqrt(n))`   `    ``# Sort all queries so that queries of` `    ``# same blocks are arranged together.` `    ``q.sort(key``=``lambda` `x: (x.L ``/``/` `block, x.R))`   `    ``currL ``=` `0` `    ``currR ``=` `0`   `    ``for` `i ``in` `range``(m):` `        ``L ``=` `q[i].L` `        ``R ``=` `q[i].R` `        ``# Add Elements of current range` `        ``while` `currR <``=` `R:` `            ``add(currR, a)` `            ``currR ``+``=` `1` `        ``while` `currL > L:` `            ``add(currL ``-` `1``, a)` `            ``currL ``-``=` `1` `        ``while` `currR > R ``+` `1``:` `            ``remove(currR ``-` `1``, a)` `            ``currR ``-``=` `1` `        ``while` `currL < L:` `            ``remove(currL, a)` `            ``currL ``+``=` `1`   `        ``# Create a new Query object with the results and add it to the list` `        ``q[i].armstrong ``=` `count_Armstrong`   `# Function to display the results of` `# queries in their initial order` `def` `printResults(q, m):` `    ``q.sort(key``=``lambda` `x: x.index)` `    ``for` `i ``in` `range``(m):` `        ``print``(q[i].armstrong)`   `if` `__name__ ``=``=` `'__main__'``:` `    ``arr ``=` `[``18``, ``153``, ``8``, ``9``, ``14``, ``5``]` `    ``n ``=` `len``(arr)`   `    ``q ``=` `[Query(``0``, ``5``, ``0``), Query(``3``, ``5``, ``1``)]` `    ``m ``=` `len``(q)`   `    ``queryResults(arr, n, q, m)`   `    ``printResults(q, m)` `    `  `#Contributed by Aditya Sharma`

## Javascript

 `// Javascript implementation to count the` `// number of Armstrong numbers` `// in subarray using MO’s algorithm`     `// Variable to represent block size.` `// This is made global so compare()` `// of sort can use it.` `let block;` `let count_Armstrong;`   `// Structure to represent` `// a query range` `function` `Query(L, R, index, armstrong) {` `  ``this``.L = L;` `  ``this``.R = R;` `  ``this``.index = index;` `    ``// Count of Armstrong` `    ``// numbers` `  ``this``.armstrong = armstrong;` `}`     `// 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.` `function` `compare(x, y) {` `    ``// Different blocks, sort by block.` `  ``if` `(Math.floor(x.L / block) !== Math.floor(y.L / block)) {` `    ``return` `Math.floor(x.L / block) - Math.floor(y.L / block);` `  ``}` `  `  `    ``// Same block, sort by R value` `  ``return` `x.R - y.R;` `}`     `// Function used to sort all` `// queries in order of their` `// index value so that results` `// of queries can be printed` `// in same order as of input` `function` `compare1(x, y) {` `  ``return` `x.index - y.index;` `}`       `// Function that return true` `// if num is armstrong` `// else return false` `function` `isArmstrong(x) {` `  ``let n = x.toString().length;` `  ``let sum1 = 0;` `  ``let temp = x;` `  ``while` `(temp > 0) {` `    ``let digit = temp % 10;` `    ``sum1 += Math.pow(digit, n);` `    ``temp = Math.floor(temp / 10);` `  ``}` `  ``return` `sum1 === x;` `}`     `// Function to Add elements` `// of current range` `function` `add(currL, a) {` `    `  `    ``// If a[currL] is a Armstrong number` `    ``// then increment count_Armstrong` `  ``if` `(isArmstrong(a[currL])) {` `    ``count_Armstrong++;` `  ``}` `}`   `function` `remove(currR, a) {` `    ``// If a[currL] is a Armstrong number` `    ``// then decrement count_Armstrong` `  ``if` `(isArmstrong(a[currR])) {` `    ``count_Armstrong--;` `  ``}` `}`   `// Function to generate the result of queries` `function` `queryResults(a, n, q, m) {` `    `  `    ``// Initialize count_Armstrong to 0` `  ``count_Armstrong = 0;` `  ``block = Math.floor(Math.sqrt(n));` `    `  `    ``// Sort all queries so that queries of` `    ``// same blocks are arranged together.` `  ``q.sort(compare);`   `  ``let currL = 0,` `    ``currR = 0;`   `  ``for` `(let i = 0; i < m; i++) {` `    ``// L and R values of current range` `    ``let 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++;` `    ``}`   `    ``q[i].armstrong = count_Armstrong;` `  ``}` `}`     `// Function to display the results of` `// queries in their initial order` `function` `printResults(q, m) {` `  ``q.sort(compare1);` `  ``for` `(let i = 0; i < m; i++) {` `    ``console.log(q[i].armstrong);` `  ``}` `}`   `// Driver Code` `const arr = [18, 153, 8, 9, 14, 5];` `const n = arr.length;`   `const q = [` `  ``new` `Query(0, 5, 0, 0),` `  ``new` `Query(3, 5, 1, 0)` `];`   `const m = q.length;`   `queryResults(arr, n, q, m);`   `printResults(q, m);`   `// This code is contributed by princekumaras`

## C#

 `// C# implementation to count the ` `// number of Armstrong numbers ` `// in subarray using MO’s algorithm `   `using` `System;` `using` `System.Collections.Generic;` `using` `System.Linq;`   `// Class to represent` `// a query range` `class` `Query` `{` `    `  `    ``// Count of Armstrong` `    ``// numbers` `    ``public` `int` `L, R, index, armstrong;`   `    ``public` `Query(``int` `L, ``int` `R, ``int` `index, ``int` `armstrong)` `    ``{` `        ``this``.L = L;` `        ``this``.R = R;` `        ``this``.index = index;` `        ``this``.armstrong = armstrong;` `    ``}` `}`   `class` `GFG` `{` `    ``// Variable to represent block size.` `    ``static` `int` `block;` `    `  `    ``// To store the count of` `    ``// Armstrong numbers` `    ``static` `int` `count_Armstrong;` `        `  `    `  `    ``// Function that return true` `    ``// if num is armstrong` `    ``// else return false` `    ``static` `bool` `isArmstrong(``int` `x)` `    ``{` `        ``int` `n = x.ToString().Length;` `        ``int` `sum1 = 0;` `        ``int` `temp = x;`   `        ``while` `(temp > 0)` `        ``{` `            ``int` `digit = temp % 10;` `            ``sum1 += (``int``)Math.Pow(digit, n);` `            ``temp /= 10;` `        ``}`   `        ``if` `(sum1 == x)` `            ``return` `true``;`   `        ``return` `false``;` `    ``}` `    `  `    `  `    ``// Function to Add elements` `    ``// of current range` `    ``static` `void` `add(``int` `currL, ``int``[] a)` `    ``{` `        ``// If a[currL] is a Armstrong number` `        ``// then increment count_Armstrong` `        ``if` `(isArmstrong(a[currL]))` `            ``count_Armstrong++;` `    ``}` `    `  `    `  `    ``// Function to remove elements` `    ``// of previous range` `    ``static` `void` `remove(``int` `currR, ``int``[] a)` `    ``{` `            `  `        ``// If a[currL] is a Armstrong number` `        ``// then decrement count_Armstrong` `        ``if` `(isArmstrong(a[currR]))` `            ``count_Armstrong--;` `    ``}`   `    ``// Function to generate the result of queries` `    ``static` `void` `queryResults(``int``[] a, ``int` `n, Query[] q, ``int` `m)` `    ``{` `        ``// Initialize count_Armstrong to 0` `        ``count_Armstrong = 0;` `        `  `        ``// Find block size` `        ``block = (``int``)(Math.Sqrt(n));` `        `  `        ``// 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.` `        ``Array.Sort(q, (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;` `        ``});`   `        ``// 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++;` `            ``}`   `            ``q[i].armstrong = count_Armstrong;` `        ``}` `    ``}` `    `  `    `  `    ``// Function to display the results of` `    ``// queries in their initial order` `    ``static` `void` `printResults(Query[] q, ``int` `m)` `    ``{` `        ``Array.Sort(q, (Query x, Query y) => ` `        `  `            ``// sort all queries` `            ``// in order of their` `            ``// index value so that results` `            ``// of queries can be printed` `            ``// in same order as of input);` `            ``x.index - y.index);`   `        ``for` `(``int` `i = 0; i < m; i++)` `        ``{` `            ``Console.WriteLine(q[i].armstrong);` `        ``}` `    ``}`   `    ``// Driver code` `    ``static` `void` `Main(``string``[] args)` `    ``{` `        ``int``[] arr = { 18, 153, 8, 9, 14, 5 };` `        ``int` `n = arr.Length;`   `        ``Query[] q = ``new` `Query;` `        ``q = ``new` `Query(0, 5, 0, 0);` `        ``q = ``new` `Query(3, 5, 1, 0);`   `        ``int` `m = q.Length;`   `        ``queryResults(arr, n, q, m);`   `        ``printResults(q, m);` `    ``}` `}`   `// This code is contributed adityashatmfh`

Output:

```4
2```

Time Complexity: O((Q*log(Q)+Q * √N)
Auxiliary Space:  O(1)
Related article: Range Queries for number of Armstrong numbers in an array with updates

My Personal Notes arrow_drop_up