给定N个正整数的数组arr []和查询数量Q ,每个查询包含两个数字L和R。任务是计算从索引L到R ,除数为奇数的数组中的元素数。
例子:
Input: arr[] = [2, 4, 5, 6, 9], Q = 3, Query[][] = { {0, 2}, {1, 3}, {1, 4} }
Output: 1 1 2
Explanation:
1st query: in 2 4 5 only 4 has an odd number of divisors.
2nd query: in 4 5 6 only 4 has an odd number of divisors.
3rd query: in 4 5 6 9 only 4, 9 has an odd number of divisors.
Input: arr[] = [1, 16, 5, 4, 9], Q = 2, Query[][] = { {1, 3}, {0, 2} }
Output: 2 1
天真的方法:天真的方法是针对每个查询在L到R的数组上进行迭代,并计算除数为奇数的[L,R]范围内的元素。如果是,则为该查询计算该元素。
时间复杂度: O(Q * N * sqrt(N))
辅助空间: O(1)
高效的方法:我们可以观察到,只有在完美平方的情况下,除数的数量才是奇数。因此,最好的解决方案是检查给定的数字是否为正整数或不在[L,R]范围内。步骤如下:
- 使用值0初始化大小为N的数组dp [] 。
- 遍历给定数组arr [] ,如果数组中的任何元素是一个完美的正方形,则将dp []中该索引处的值更新为1 。
- 为了有效地计算每个查询的答案,我们将预先计算答案。
- 我们将对数组dp []进行前缀求和,对于[L,R]范围内的每个查询,答案将由以下公式给出:
OddDivisorCount(L, R) = DP[R] - DP[L-1]
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function count the number of elements
// having odd number of divisors
void OddDivisorsCount(
int n, int q, int a[],
vector > Query)
{
// Initialise dp[] array
int DP[n] = { 0 };
// Precomputation
for (int i = 0; i < n; i++) {
int x = sqrt(a[i]);
if (x * x == a[i])
DP[i] = 1;
}
// Find the Prefix Sum
for (int i = 1; i < n; i++) {
DP[i] = DP[i - 1] + DP[i];
}
int l, r;
// Iterate for each query
for (int i = 0; i < q; i++) {
l = Query[i].first;
r = Query[i].second;
// Find the answer for each query
if (l == 0) {
cout << DP[r] << endl;
}
else {
cout << DP[r] - DP[l - 1]
<< endl;
}
}
}
// Driver Code
int main()
{
int N = 5;
int Q = 3;
// Given array arr[]
int arr[] = { 2, 4, 5, 6, 9 };
// Given Query
vector > Query
Query
= { { 0, 2 }, { 1, 3 }, { 1, 4 } };
// Function Call
OddDivisorsCount(N, Q, arr, Query);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
class GFG{
static class pair
{
int first, second;
public pair(int first, int second)
{
this.first = first;
this.second = second;
}
}
// Function count the number of elements
// having odd number of divisors
static void OddDivisorsCount(int n, int q,
int a[],
pair []Query)
{
// Initialise dp[] array
int DP[] = new int[n];
// Precomputation
for(int i = 0; i < n; i++)
{
int x = (int)Math.sqrt(a[i]);
if (x * x == a[i])
DP[i] = 1;
}
// Find the Prefix Sum
for(int i = 1; i < n; i++)
{
DP[i] = DP[i - 1] + DP[i];
}
int l, r;
// Iterate for each query
for(int i = 0; i < q; i++)
{
l = Query[i].first;
r = Query[i].second;
// Find the answer for each query
if (l == 0)
{
System.out.print(DP[r] + "\n");
}
else
{
System.out.print(DP[r] -
DP[l - 1] + "\n");
}
}
}
// Driver Code
public static void main(String[] args)
{
int N = 5;
int Q = 3;
// Given array arr[]
int arr[] = { 2, 4, 5, 6, 9 };
// Given Query
pair []Query = { new pair(0, 2),
new pair(1, 3),
new pair(1, 4) };
// Function Call
OddDivisorsCount(N, Q, arr, Query);
}
}
// This code is contributed by amal kumar choubey
Python3
# Python3 program for the above approach
import math
# Function count the number of elements
# having odd number of divisors
def OddDivisorsCount(n, q, a, Query):
# Initialise dp[] array
DP = [0 for i in range(n)]
# Precomputation
for i in range(n):
x = int(math.sqrt(a[i]));
if (x * x == a[i]):
DP[i] = 1;
# Find the Prefix Sum
for i in range(1, n):
DP[i] = DP[i - 1] + DP[i];
l = 0
r = 0
# Iterate for each query
for i in range(q):
l = Query[i][0];
r = Query[i][1];
# Find the answer for each query
if (l == 0):
print(DP[r])
else:
print(DP[r] - DP[l - 1])
# Driver code
if __name__=="__main__":
N = 5;
Q = 3;
# Given array arr[]
arr = [ 2, 4, 5, 6, 9 ]
# Given Query
Query = [ [ 0, 2 ],
[ 1, 3 ],
[ 1, 4 ] ]
# Function call
OddDivisorsCount(N, Q, arr, Query);
# This code is contributed by rutvik_56
C#
// C# program for the above approach
using System;
class GFG{
class pair
{
public int first, second;
public pair(int first, int second)
{
this.first = first;
this.second = second;
}
}
// Function count the number of elements
// having odd number of divisors
static void OddDivisorsCount(int n, int q,
int []a,
pair []Query)
{
// Initialise []dp array
int []DP = new int[n];
// Precomputation
for(int i = 0; i < n; i++)
{
int x = (int)Math.Sqrt(a[i]);
if (x * x == a[i])
DP[i] = 1;
}
// Find the Prefix Sum
for(int i = 1; i < n; i++)
{
DP[i] = DP[i - 1] + DP[i];
}
int l, r;
// Iterate for each query
for(int i = 0; i < q; i++)
{
l = Query[i].first;
r = Query[i].second;
// Find the answer for each query
if (l == 0)
{
Console.Write(DP[r] + "\n");
}
else
{
Console.Write(DP[r] -
DP[l - 1] + "\n");
}
}
}
// Driver Code
public static void Main(String[] args)
{
int N = 5;
int Q = 3;
// Given array []arr
int []arr = { 2, 4, 5, 6, 9 };
// Given Query
pair []Query = { new pair(0, 2),
new pair(1, 3),
new pair(1, 4) };
// Function Call
OddDivisorsCount(N, Q, arr, Query);
}
}
// This code is contributed by gauravrajput1
1
1
2
时间复杂度:
- 预计算:O(N)
- 对于每个查询:O(1)
辅助空间: O(1)