给定大小为N的数组arr [] ,任务是找到所有索引对(i,j)的底值(arr [i] / arr [j])的总和。
例子:
Input: arr[] = { 1, 2, 3 }
Output: 9
Explanation:
Sum = (arr[i] / arr[j]) (a[0] / a[0]) + (a[0] / a[1]) + (a[0] / a[2]) + (a[1] / a[1]) + (a[1] / a[2]) + (a[2] / a[2]) + (a[1] / a[0]) + (a[2] / a[0]) + (a[2] / a[1]) = 1 + 0 + 0 + 1 + 0 + 1 + 2 + 3 + 1 = 9
Therefore, the required output is 9.
Input: arr[] = { 4, 2, 5, 6 }
Output: 14
天真的方法:解决此问题的最简单方法是生成数组的所有可能对,并为每个对将结果的下限递增(arr [i] / arr [j]) 。最后,打印获得的结果。
时间复杂度: O(N 2 )
辅助空间: O(N)
高效的方法:可以基于以下观察来优化上述方法:
If a sequence is X, X + 1, …, 2 * X – 1, 2 * X, …., 3 * X – 1
(X) / X + (X + 1) / X + … + (2 * X – 1) / X + (2 * X) / X + … + (3 * X – 1) / X
= 1 + 1 + … + 1 + 2 + … + 2
For first X consecutive numbers, the floor value of (X + i) / X = 1
For next X consecutive numbers, the floor value of (2 * X + i) / X = 2
and so on…
请按照以下步骤解决问题:
- 初始化一个数组,例如freq [] ,以存储数组元素的频率。
- 初始化一个数组,例如preFreq [] ,以存储count []数组的前缀和。
- preFreq [j] – preFreq [i]存储值在[i,j]范围内的数组元素的计数。
- 找到数组中最大的元素,例如Max 。
- 在[1,Max]范围内迭代。对于每个第i个值,使用preFreq []数组对值位于[i,j]范围内的数组元素进行计数,其中j是i的倍数,然后将结果以frequency [i] *(preFreq [j – 1] – preFreq [j – i – 1])*(j / i – 1) 。
- 最后,打印获得的结果。
下面是上述方法的实现:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Stores the maximum value of
// an array element
const int N = 3e5;
// Function to find the sum of
// floor(a[i]/a[j]) of all pairs (i, j)
void getFloorSum(int arr[], int n)
{
// Stores frequency of
// array element
int freq[N] = { 0 };
// Stores prefix sum
// array of frequency[]
int preFreq[N] = { 0 };
// Traverse the array
for (int i = 0; i < n; i++) {
// Update frequency
// of arr[i]
freq[arr[i]]++;
}
// Compute the prefix sum
// of frequency[]
for (int i = 1; i < N; i++) {
preFreq[i]
= preFreq[i - 1] + freq[i];
}
// Stores the sum of floor(a[i]/a[j])
// of all pairs (i, j)
int ans = 0;
// Iterate over the range [1, Max]
for (int i = 1; i <= N; i++) {
// Find the count of numbers in
// the range [i * K, i * (K + 1))
// and update the result
for (int j = i; j <= N; j += i) {
// Stores count of numbers
// in range[j - i - 1, j - 1]
int X = (preFreq[j - 1]
- preFreq[j - i - 1]);
// Update ans
ans += X * (j / i - 1) * freq[i];
}
}
// Print the answer
cout << ans;
}
// Driver Code
int main()
{
// Given array
int arr[] = { 1, 2, 3 };
// Stores the size of array
int n = sizeof(arr) / sizeof(arr[0]);
getFloorSum(arr, n);
return 0;
}
Java
// Java program to implement
// the above approach
import java.util.*;
class GFG{
// Stores the maximum value of
// an array element
static int N = (int) 3e5;
// Function to find the sum of
// Math.floor(a[i]/a[j]) of all pairs (i, j)
static void getFloorSum(int arr[], int n)
{
// Stores frequency of
// array element
int freq[] = new int[N];
// Stores prefix sum
// array of frequency[]
int preFreq[] = new int[N];
// Traverse the array
for (int i = 0; i < n; i++)
{
// Update frequency
// of arr[i]
freq[arr[i]]++;
}
// Compute the prefix sum
// of frequency[]
for (int i = 1; i < N; i++)
{
preFreq[i]
= preFreq[i - 1] + freq[i];
}
// Stores the sum of Math.floor(a[i]/a[j])
// of all pairs (i, j)
int ans = 0;
// Iterate over the range [1, Max]
for (int i = 1; i < N; i++)
{
// Find the count of numbers in
// the range [i * K, i * (K + 1))
// and update the result
for (int j = i; j < N; j += i)
{
// Stores count of numbers
// in range[j - i - 1, j - 1]
int X = (preFreq[j - 1]
- preFreq[Math.abs(j - i - 1)]);
// Update ans
ans += X * (j / i - 1) * freq[i];
}
}
// Print the answer
System.out.print(ans);
}
// Driver Code
public static void main(String[] args)
{
// Given array
int arr[] = { 1, 2, 3 };
// Stores the size of array
int n = arr.length;
getFloorSum(arr, n);
}
}
// This code is contributed by shikhasingrajput
Python3
# Python3 program to implement
# the above approach
# Stores the maximum value of
# an array element
N = 10**5
# Function to find the sum of
# floor(a[i]/a[j]) of all pairs (i, j)
def getFloorSum(arr, n):
# Stores frequency of
# array element
freq = [ 0 for i in range(N + 1)]
# Stores prefix sum
# array of frequency[]
preFreq = [ 0 for i in range(N + 1)]
# Traverse the array
for i in range(n):
# Update frequency
# of arr[i]
freq[arr[i]] += 1
# Compute the prefix sum
# of frequency[]
for i in range(1, N):
preFreq[i] = preFreq[i - 1] + freq[i]
# Stores the sum of floor(a[i]/a[j])
# of all pairs (i, j)
ans = 0
# Iterate over the range [1, Max]
for i in range(1, N + 1):
# Find the count of numbers in
# the range [i * K, i * (K + 1))
# and update the result
for j in range(i, N + 1, i):
# Stores count of numbers
# in range[j - i - 1, j - 1]
X = (preFreq[j - 1] - preFreq[j - i - 1])
# Update ans
ans += X * (j // i - 1) * freq[i]
# Prthe answer
print(ans)
# Driver Code
if __name__ == '__main__':
# Given array
arr = [1, 2, 3]
# Stores the size of array
n = len(arr)
getFloorSum(arr, n)
# This code is contributed by mohit kumar 29
C#
// C# program to implement
// the above approach
using System;
class GFG{
// Stores the maximum value of
// an array element
static int N = (int)3e5;
// Function to find the sum of
// Math.Floor(a[i]/a[j]) of all
// pairs (i, j)
static void getFloorSum(int []arr, int n)
{
// Stores frequency of
// array element
int []freq = new int[N];
// Stores prefix sum
// array of frequency[]
int []preFreq = new int[N];
// Traverse the array
for(int i = 0; i < n; i++)
{
// Update frequency
// of arr[i]
freq[arr[i]]++;
}
// Compute the prefix sum
// of frequency[]
for(int i = 1; i < N; i++)
{
preFreq[i] = preFreq[i - 1] + freq[i];
}
// Stores the sum of Math.Floor(a[i]/a[j])
// of all pairs (i, j)
int ans = 0;
// Iterate over the range [1, Max]
for(int i = 1; i < N; i++)
{
// Find the count of numbers in
// the range [i * K, i * (K + 1))
// and update the result
for(int j = i; j < N; j += i)
{
// Stores count of numbers
// in range[j - i - 1, j - 1]
int X = (preFreq[j - 1] -
preFreq[Math.Abs(j - i - 1)]);
// Update ans
ans += X * (j / i - 1) * freq[i];
}
}
// Print the answer
Console.Write(ans);
}
// Driver Code
public static void Main(String[] args)
{
// Given array
int []arr = { 1, 2, 3 };
// Stores the size of array
int n = arr.Length;
getFloorSum(arr, n);
}
}
// This code is contributed by shikhasingrajput
9
时间复杂度: O(N + M * log(log(M)),其中M是最大的数组元素
辅助空间: O(M)