📌  相关文章
📜  给定数组的可能对的总和

📅  最后修改于: 2021-05-18 01:23:07             🧑  作者: Mango

给定N个正整数的数组arr [] 。对于所有可能的对(x,y) ,任务是找到x / y的总和。

注意:如果(x / y)的小数部分为&ge 0.5,则添加(x / y)的ceil,否则添加(x / y)的下限。

例子:

天真的方法:这个想法是在给定的数组中生成所有可能的对,并为每对(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))