// 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[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 adityashatmfh