Q查询的给定范围内的完美数计数
给定一个由N对组成的数组arr[] ,其中每对代表{L, R}形式的查询,任务是在给定范围内为每个查询找到完美数字的计数。
例子:
Input: arr[][] = {{1, 10}, {10, 20}, {20, 30}}
Output: 1 1 1
Explanation:
- Query(1, 10): Perfect numbers in the range is only 6.
- Query(10, 20): There are no perfect numbers in the range.
- Query(20, 30): The perfect number in the range is only 28.
Input: arr[][] = {{1, 1000}, {1000, 2000}, {2000, 3000}
Output: 3 0 0
Explanation:
- Query(1, 1000): Perfect numbers in the range are 6, 28, and 496.
- Query(1000, 2000): There are no perfect numbers in the range.
- Query(2000, 3000): There are no perfect numbers in the range.
朴素方法:最简单的方法是,遍历每个查询的范围并检查一个数字是否为完美数字,然后为各个查询打印该范围内完美数字的计数。
时间复杂度: O(N*M*√M)),其中 M 是范围的最大尺寸。
辅助空间: O(1)
高效方法:上述方法可以通过使用前缀和数组技术将完美数字的计数从1预存到每个其他数字来进行优化,这会导致每个查询的时间计算恒定。请按照以下步骤解决问题:
- 通过遍历数组arr[]找到范围右边界的最大值并将其存储在一个变量中,比如MAX。
- 初始化一个数组,比如大小为MAX+1的prefix[] ,每个元素的值为0 ,其中prefix[i]存储完美数的计数,直到i 。
- 使用变量i遍历范围[2, MAX]并执行以下操作:
- 将prefix[i]更新为prefix[i-1] ,然后检查当前整数i是否为完美数,然后将prefix[i]增加1。
- 遍历数组arr[]并在每次迭代中打印当前范围内完美数字的计数, [L, R]作为前缀[R] – 前缀[L-1]。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
const int MAX = 100005;
// Function to check whether a number
// is perfect Number
bool isPerfect(long long int N)
{
// Stores sum of divisors
long long int sum = 1;
// Iterate over the range[2, sqrt(N)]
for (long long int i = 2; i * i <= N; i++) {
if (N % i == 0) {
if (i * i != N)
sum = sum + i + N / i;
else
sum = sum + i;
}
}
// If sum of divisors is equal to
// N, then N is a perfect number
if (sum == N && N != 1)
return true;
return false;
}
// Function to find count of perfect
// numbers in a given range
void Query(int arr[][2], int N)
{
// Stores the count of perfect Numbers
// upto a every number less than MAX
int prefix[MAX + 1] = { 0 };
// Iterate over the range [1, MAX]
for (int i = 2; i <= MAX; i++) {
prefix[i] = prefix[i - 1] + isPerfect(i);
}
// Traverse the array arr[]
for (int i = 0; i < N; i++) {
// Print the count of perfect numbers
// in the range [arr[i][0], arr[i][1]]
cout << prefix[arr[i][1]] - prefix[arr[i][0] - 1]
<< " ";
}
}
// Driver Code
int main()
{
int arr[][2]
= { { 1, 1000 }, { 1000, 2000 }, { 2000, 3000 } };
int N = sizeof(arr) / sizeof(arr[0]);
Query(arr, N);
}
Java
// C++ program for the above approach
import java.util.*;
public class MyClass
{
static int MAX = 100005;
// Function to check whether a number
// is perfect Number
static int isPerfect(long N)
{
// Stores sum of divisors
long sum = 1;
// Iterate over the range[2, sqrt(N)]
for (long i = 2; i * i <= N; i++) {
if (N % i == 0) {
if (i * i != N)
sum = sum + i + N / i;
else
sum = sum + i;
}
}
// If sum of divisors is equal to
// N, then N is a perfect number
if (sum == N && N != 1)
return 1;
return 0;
}
// Function to find count of perfect
// numbers in a given range
static void Query(int arr[][], int N)
{
// Stores the count of perfect Numbers
// upto a every number less than MAX
int []prefix = new int [MAX + 1];
Arrays.fill(prefix,0);
// Iterate over the range [1, MAX]
for (int i = 2; i <= MAX; i++) {
prefix[i] = prefix[i - 1] + isPerfect(i);
}
// Traverse the array arr[]
for (int i = 0; i < N; i++)
{
// Print the count of perfect numbers
// in the range [arr[i][0], arr[i][1]]
System.out.print( prefix[arr[i][1]] - prefix[arr[i][0] - 1]+ " ");
}
}
// Driver Code
public static void main(String args[])
{
int [][]arr = { { 1, 1000 }, { 1000, 2000 }, { 2000, 3000 } };
int N = arr.length;
Query(arr, N);
}
}
// This code is contributed by SoumikMondal
Python3
# python 3 program for the above approach
MAX = 100005
from math import sqrt
# Function to check whether a number
# is perfect Number
def isPerfect(N):
# Stores sum of divisors
sum = 1
# Iterate over the range[2, sqrt(N)]
for i in range(2,int(sqrt(N))+1,1):
if (N % i == 0):
if (i * i != N):
sum = sum + i + N // i
else:
sum = sum + i
# If sum of divisors is equal to
# N, then N is a perfect number
if (sum == N and N != 1):
return True
return False
# Function to find count of perfect
# numbers in a given range
def Query(arr, N):
# Stores the count of perfect Numbers
# upto a every number less than MAX
prefix = [0 for i in range(MAX + 1)]
# Iterate over the range [1, MAX]
for i in range(2,MAX+1,1):
prefix[i] = prefix[i - 1] + isPerfect(i)
# Traverse the array arr[]
for i in range(N):
# Print the count of perfect numbers
# in the range [arr[i][0], arr[i][1]]
print(prefix[arr[i][1]] - prefix[arr[i][0] - 1],end= " ")
# Driver Code
if __name__ == '__main__':
arr = [[1, 1000],[1000, 2000],[2000, 3000]]
N = len(arr)
Query(arr, N)
# This code is contributed by SURENDRA_GANGWAR.
C#
// C# program for the above approach
using System;
public class MyClass {
static int MAX = 100005;
// Function to check whether a number
// is perfect Number
static int isPerfect(long N)
{
// Stores sum of divisors
long sum = 1;
// Iterate over the range[2, sqrt(N)]
for (long i = 2; i * i <= N; i++) {
if (N % i == 0) {
if (i * i != N)
sum = sum + i + N / i;
else
sum = sum + i;
}
}
// If sum of divisors is equal to
// N, then N is a perfect number
if (sum == N && N != 1)
return 1;
return 0;
}
// Function to find count of perfect
// numbers in a given range
static void Query(int[, ] arr, int N)
{
// Stores the count of perfect Numbers
// upto a every number less than MAX
int[] prefix = new int[MAX + 1];
// Arrays.fill(prefix,0);
// Iterate over the range [1, MAX]
for (int i = 2; i <= MAX; i++) {
prefix[i] = prefix[i - 1] + isPerfect(i);
}
// Traverse the array arr[]
for (int i = 0; i < N; i++) {
// Print the count of perfect numbers
// in the range [arr[i][0], arr[i][1]]
Console.Write(prefix[arr[i, 1]]
- prefix[arr[i, 0] - 1] + " ");
}
}
// Driver Code
public static void Main()
{
int[, ] arr = { { 1, 1000 },
{ 1000, 2000 },
{ 2000, 3000 } };
int N = arr.GetLength(0);
Query(arr, N);
}
}
// This code is contributed by ukasp.
Javascript
输出
3 0 0
时间复杂度: O(M*√M+ N),其中 M 是最大的右边界。
辅助空间: O(M)