给定N个正整数的数组arr [] 。对于所有可能的对(x,y) ,任务是找到x / y的总和。
注意:如果(x / y)的小数部分为&ge 0.5,则添加(x / y)的ceil,否则添加(x / y)的下限。
例子:
Input: arr[] = {1, 2, 3}
Output: 12
Explanation:
All possible pairs with division are:
(1/1) = 1, (1/2) = 1, (1/3) = 0
(2/1) = 2, (2/2) = 1, (2/3) = 1
(3/1) = 3, (3/2) = 2, (3/3) = 1
Sum = 1 + 1 + 0 + 2 + 1 + 1 + 3 + 2 + 1 = 12.
Input: arr[] = {1, 2, 3, 4}
Output: 22
Explanation:
All possible pairs with division are:
(1/1) = 1, (1/2) = 1, (1/3) = 0, (1/4) = 0
(2/1) = 2, (2/2) = 1, (2/3) = 1, (2/4) = 1
(3/1) = 3, (3/2) = 2, (3/3) = 1, (3/4) = 1
(4/1) = 4, (4/2) = 2, (4/3) = 1, (4/4) = 1
Sum = 1 + 1 + 0 + 0 + 2 + 1 + 1 + 1 + 3 + 2 + 1 + 1 + 4 + 2 + 1 + 1 = 22.
天真的方法:这个想法是在给定的数组中生成所有可能的对,并为每对(x,y)找到(x / y)的总和。
时间复杂度: O(N 2 )
高效方法:
为了优化上述方法,我们必须计算频率阵列,其中freq [i]表示数字i的出现次数。
- 对于任何给定的数字X,除以X之外,所有范围为[0.5X,1.5X]的数字都将为答案贡献1。类似地,所有范围为[1.5X,2.5X]的数字将导致2贡献给答案。答案除以X。
- 概括这个事实,从[[n-0.5)X,(n + 0.5)X]的所有数字除以X都会对答案产生n。
- 因此,对于介于1到N范围内的每个数字P,我们只需计算频率数组的前缀和就可以获得位于给定范围[L,R]中的数字的计数。
- 对于数字P,我们需要查询最多N / P次的范围。
下面是上述方法的实现:
C++
// C++ implementation to compute the
// sum of division of all the possible
// pairs for the given array
#include
#define ll long long
using namespace std;
// Function to compute the sum
int func(int arr[], int n)
{
double ans = 0;
int maxx = 0;
double freq[100005] = { 0 };
int temp;
// counting frequency
// of each term
// and finding maximum
// among it
for (int i = 0; i < n; i++) {
temp = arr[i];
freq[temp]++;
maxx = max(maxx, temp);
}
// Making cumulative frequency
for (int i = 1; i <= maxx; i++) {
freq[i] += freq[i - 1];
}
for (int i = 1; i <= maxx; i++) {
if (freq[i]) {
i = (double)i;
double j;
ll value = 0;
// Taking the ceil value
double cur = ceil(0.5 * i) - 1.0;
for (j = 1.5;; j++) {
int val = min(maxx, (int)(ceil(i * j) - 1.0));
int times = (freq[i] - freq[i - 1]), con = j - 0.5;
// nos. in [(n-0.5)X, (n+0.5)X)
// range will add n to the ans
ans += times * con * (freq[(int)val] - freq[(int)cur]);
cur = val;
if (val == maxx)
break;
}
}
}
// Return the final result
return (ll)ans;
}
// Driver code
int main()
{
int arr[] = { 1, 2, 3 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << func(arr, n) << endl;
return 0;
}
Java
// Java implementation to compute the
// sum of division of all the possible
// pairs for the given array
class GFG{
// Function to compute the sum
static long func(int arr[], int n)
{
double ans = 0;
int maxx = 0;
double freq[] = new double[100005];
int temp;
// Counting frequency of each term
// and finding maximum among it
for(int i = 0; i < n; i++)
{
temp = arr[i];
freq[temp]++;
maxx = Math.max(maxx, temp);
}
// Making cumulative frequency
for(int i = 1; i <= maxx; i++)
{
freq[i] += freq[i - 1];
}
for(int i = 1; i <= maxx; i++)
{
if (freq[i] != 0)
{
double j;
// Taking the ceil value
double cur = Math.ceil(0.5 * i) - 1.0;
for(j = 1.5;; j++)
{
int val = Math.min(maxx,
(int)(Math.ceil(i * j) - 1.0));
int times = (int)(freq[i] -
freq[i - 1]),
con = (int)(j - 0.5);
// nos. in [(n-0.5)X, (n+0.5)X)
// range will add n to the ans
ans += times * con * (freq[(int)val] -
freq[(int)cur]);
cur = val;
if (val == maxx)
break;
}
}
}
// Return the final result
return (long)ans;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 1, 2, 3 };
int n = arr.length;
System.out.print(func(arr, n) + "\n");
}
}
// This code is contributed by Amit Katiyar
Python3
# Python3 program to compute the sum
# of division of all the possible
# pairs for the given array
from math import *
# Function to compute the sum
def func (arr, n):
ans = 0
maxx = 0
freq = [0] * 100005
temp = 0
# Counting frequency of each term
# and finding maximum among it
for i in range(n):
temp = arr[i]
freq[temp] += 1
maxx = max(maxx, temp)
# Making cumulative frequency
for i in range(1, maxx + 1):
freq[i] += freq[i - 1]
for i in range(1, maxx + 1):
if (freq[i]):
value = 0
# Taking the ceil value
cur = ceil(0.5 * i) - 1.0
j = 1.5
while (1):
val = min(maxx, (ceil(i * j) - 1.0))
times = (freq[i] - freq[i - 1])
con = j - 0.5
# nos. in [(n-0.5)X , (n+0.5)X)
# range will add n to the ans
ans += times * con * (freq[int(val)] -
freq[int(cur)])
cur = val
if (val == maxx):
break
j += 1
return int(ans)
# Driver code
if __name__ == '__main__':
arr = [ 1, 2, 3 ]
n = len(arr)
print(func(arr, n))
# This code is contributed by himanshu77
C#
// C# implementation to compute the
// sum of division of all the possible
// pairs for the given array
using System;
class GFG{
// Function to compute the sum
static long func(int []arr, int n)
{
double ans = 0;
int maxx = 0;
double []freq = new double[100005];
int temp;
// Counting frequency of each term
// and finding maximum among it
for(int i = 0; i < n; i++)
{
temp = arr[i];
freq[temp]++;
maxx = Math.Max(maxx, temp);
}
// Making cumulative frequency
for(int i = 1; i <= maxx; i++)
{
freq[i] += freq[i - 1];
}
for(int i = 1; i <= maxx; i++)
{
if (freq[i] != 0)
{
double j;
// Taking the ceil value
double cur = Math.Ceiling(0.5 * i) - 1.0;
for(j = 1.5;; j++)
{
int val = Math.Min(maxx,
(int)(Math.Ceiling(i * j) - 1.0));
int times = (int)(freq[i] -
freq[i - 1]),
con = (int)(j - 0.5);
// nos. in [(n-0.5)X, (n+0.5)X)
// range will add n to the ans
ans += times * con * (freq[(int)val] -
freq[(int)cur]);
cur = val;
if (val == maxx)
break;
}
}
}
// Return the readonly result
return (long)ans;
}
// Driver code
public static void Main(String[] args)
{
int []arr = { 1, 2, 3 };
int n = arr.Length;
Console.Write(func(arr, n) + "\n");
}
}
// This code is contributed by Amit Katiyar
12
时间复杂度: O(N * log(N))