给定一个由N个元素组成的数组arr []和由L和R表示范围的Q查询组成的任务是打印子数组[L,R]中的阿姆斯特朗数。
例子:
Input: arr[] = {18, 153, 8, 9, 14, 5}
Query 1: query(L=0, R=5)
Query 2: query(L=3, R=5)
Output: 4
2
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}
方法:
这个想法是使用MO的算法对所有查询进行预处理,以便一个查询的结果可以在下一个查询中使用。
- 对所有查询进行排序,将L值从0到√n– 1的查询放在一起,然后是从√n到2×√n– 1的查询,依此类推。块中的所有查询均按R值的升序排序。
- 一个接一个地处理所有查询,并增加阿姆斯壮编号的数量,并将结果存储在结构中。
- 让“ count_Armstrong ”存储上一个查询中的阿姆斯壮编号的数量。
- 删除先前查询的多余元素,并为当前查询添加新元素。例如,如果上一个查询为[0,8],而当前查询为[3,9],则删除元素arr [0],arr [1]和arr [2]并添加arr [9]。
- 为了显示结果,请按查询顺序对查询进行排序。
添加元素
- 如果当前元素是Armstrong编号,则增加count_Armstrong 。
移除元素
- 如果当前元素是Armstrong编号,则递减count_Armstrong 。
下面是上述方法的实现:
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[0]);
Query q[] = { { 0, 5, 0, 0 },
{ 3, 5, 1, 0 } };
int m = sizeof(q) / sizeof(q[0]);
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
输出:
4
2
时间复杂度: O(Q *√N)
相关文章:具有更新的数组中的阿姆斯壮数的范围查询