给定一个由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
Javascript
1
1
2
时间复杂度:
- 预计算:O(N)
- 对于每个查询:O(1)
辅助空间: O(1)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。