📌  相关文章
📜  满足给定条件的数组中的三元组计数

📅  最后修改于: 2021-04-29 04:31:02             🧑  作者: Mango

给定N个元素的数组arr [] ,任务是查找三元组(arr [i],arr [j],arr [k])的数量,使得(arr [i] + arr [j] + arr [ k] = L)(L%arr [i] = L%arr [j] = L%arr [k] = 0

例子:

方法:

  • 请考虑以下方程式:
  • 对于从1N的所有i 。考虑将arr [i]作为三元组的中间元素。并找到等式1 / a + 1 / b + 1 / c = 1的所有可能解的三元组的相应第一和第三元素。找到所有情况的答案,并将它们添加到最终答案中。
  • 保持数组中出现arr [i]的索引。对于给定的等式X的可能解,对于每个数字arr [i]保持该数字作为三元组的中间元素,并找到第一个和第三个元素。对第一个和第三个元素的可用索引集进行二进制搜索,以查找第一个元素的出现次数从1i – 1以及第三个元素的出现次数从i + 1N。将两个值相乘并将其添加到最终答案中。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
#define ll long long int
#define MAX 100001
#define ROW 10
#define COl 3
  
vector indices[MAX];
  
// All possible solutions of the
// equation 1/a + 1/b + 1/c = 1
int test[ROW][COl] = { { 2, 3, 6 },
                       { 2, 4, 4 },
                       { 2, 6, 3 },
                       { 3, 2, 6 },
                       { 3, 3, 3 },
                       { 3, 6, 2 },
                       { 4, 2, 4 },
                       { 4, 4, 2 },
                       { 6, 2, 3 },
                       { 6, 3, 2 } };
  
// Function to find the triplets
int find_triplet(int array[], int n)
{
    int answer = 0;
  
    // Storing indices of the elements
    for (int i = 0; i < n; i++) {
        indices[array[i]].push_back(i);
    }
  
    for (int i = 0; i < n; i++) {
        int y = array[i];
  
        for (int j = 0; j < ROW; j++) {
            int s = test[j][1] * y;
  
            // Check if y can act as the middle
            // element of triplet with the given
            // solution of 1/a + 1/b + 1/c = 1
            if (s % test[j][0] != 0)
                continue;
            if (s % test[j][2] != 0)
                continue;
  
            int x = s / test[j][0];
            ll z = s / test[j][2];
            if (x > MAX || z > MAX)
                continue;
  
            int l = 0;
            int r = indices[x].size() - 1;
  
            int first = -1;
  
            // Binary search to find the number of
            // possible values of the first element
            while (l <= r) {
                int m = (l + r) / 2;
  
                if (indices[x][m] < i) {
                    first = m;
                    l = m + 1;
                }
                else {
                    r = m - 1;
                }
            }
  
            l = 0;
            r = indices[z].size() - 1;
  
            int third = -1;
  
            // Binary search to find the number of
            // possible values of the third element
            while (l <= r) {
                int m = (l + r) / 2;
  
                if (indices[z][m] > i) {
                    third = m;
                    r = m - 1;
                }
                else {
                    l = m + 1;
                }
            }
  
            if (first != -1 && third != -1) {
  
                // Contribution to the answer would
                // be the multiplication of the possible
                // values for the first and the third element
                answer += (first + 1) * (indices[z].size() - third);
            }
        }
    }
  
    return answer;
}
  
// Driver code
int main()
{
    int array[] = { 2, 4, 5, 6, 7 };
    int n = sizeof(array) / sizeof(array[0]);
  
    cout << find_triplet(array, n);
  
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
  
class GFG
{
  
static int MAX = 100001;
static int ROW = 10;
static int COl = 3;
  
static Vector []indices = new Vector[MAX];
  
// All possible solutions of the
// equation 1/a + 1/b + 1/c = 1
static int test[][] = { { 2, 3, 6 }, { 2, 4, 4 },
                        { 2, 6, 3 }, { 3, 2, 6 },
                        { 3, 3, 3 }, { 3, 6, 2 },
                        { 4, 2, 4 }, { 4, 4, 2 },
                        { 6, 2, 3 }, { 6, 3, 2 } };
  
// Function to find the triplets
static int find_triplet(int array[], int n)
{
    int answer = 0;
    for (int i = 0; i < MAX; i++)
    {
        indices[i] = new Vector<>();
    }
      
    // Storing indices of the elements
    for (int i = 0; i < n; i++)
    {
        indices[array[i]].add(i);
    }
  
    for (int i = 0; i < n; i++)
    {
        int y = array[i];
  
        for (int j = 0; j < ROW; j++) 
        {
            int s = test[j][1] * y;
  
            // Check if y can act as the middle
            // element of triplet with the given
            // solution of 1/a + 1/b + 1/c = 1
            if (s % test[j][0] != 0)
                continue;
            if (s % test[j][2] != 0)
                continue;
  
            int x = s / test[j][0];
            int z = s / test[j][2];
            if (x > MAX || z > MAX)
                continue;
  
            int l = 0;
            int r = indices[x].size() - 1;
  
            int first = -1;
  
            // Binary search to find the number of
            // possible values of the first element
            while (l <= r)
            {
                int m = (l + r) / 2;
  
                if (indices[x].get(m) < i)
                {
                    first = m;
                    l = m + 1;
                }
                else 
                {
                    r = m - 1;
                }
            }
  
            l = 0;
            r = indices[z].size() - 1;
  
            int third = -1;
  
            // Binary search to find the number of
            // possible values of the third element
            while (l <= r) 
            {
                int m = (l + r) / 2;
  
                if (indices[z].get(m) > i) 
                {
                    third = m;
                    r = m - 1;
                }
                else 
                {
                    l = m + 1;
                }
            }
  
            if (first != -1 && third != -1) 
            {
  
                // Contribution to the answer would
                // be the multiplication of the possible
                // values for the first and the third element
                answer += (first + 1) * (indices[z].size() - third);
            }
        }
    }
    return answer;
}
  
// Driver code
public static void main(String []args) 
{
    int array[] = { 2, 4, 5, 6, 7 };
    int n = array.length;
  
    System.out.println(find_triplet(array, n));
}
}
  
// This code is contributed by Rajput-Ji


Python3
# Python3 implementation of the approach
MAX = 100001
ROW = 10
COL = 3
  
indices = [0] * MAX
  
# All possible solutions of the
# equation 1/a + 1/b + 1/c = 1
test = [[2, 3, 6], [2, 4, 4], 
        [2, 6, 3], [3, 2, 6], 
        [3, 3, 3], [3, 6, 2],
        [4, 2, 4], [4, 4, 2], 
        [6, 2, 3], [6, 3, 2]]
  
# Function to find the triplets
def find_triplet(array, n):
    answer = 0
  
    for i in range(MAX):
        indices[i] = []
  
    # Storing indices of the elements
    for i in range(n):
        indices[array[i]].append(i)
  
    for i in range(n):
        y = array[i]
  
        for j in range(ROW):
            s = test[j][1] * y
  
            # Check if y can act as the middle
            # element of triplet with the given
            # solution of 1/a + 1/b + 1/c = 1
            if s % test[j][0] != 0:
                continue
            if s % test[j][2] != 0:
                continue
  
            x = s // test[j][0]
            z = s // test[j][2]
            if x > MAX or z > MAX:
                continue
  
            l = 0
            r = len(indices[x]) - 1
            first = -1
  
            # Binary search to find the number of
            # possible values of the first element
            while l <= r:
                m = (l + r) // 2
  
                if indices[x][m] < i:
                    first = m
                    l = m + 1
                else:
                    r = m - 1
  
            l = 0
            r = len(indices[z]) - 1
            third = -1
  
            # Binary search to find the number of
            # possible values of the third element
            while l <= r:
                m = (l + r) // 2
  
                if indices[z][m] > i:
                    third = m
                    r = m - 1
                else:
                    l = m + 1
  
            if first != -1 and third != -1:
  
                # Contribution to the answer would
                # be the multiplication of the possible
                # values for the first and the third element
                answer += (first + 1) * (len(indices[z]) - third)
    return answer
  
# Driver Code
if __name__ == "__main__":
    array = [2, 4, 5, 6, 7]
    n = len(array)
  
    print(find_triplet(array, n))
  
# This code is contributed by
# sanjeev2552


C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
  
class GFG
{
  
static int MAX = 100001;
static int ROW = 10;
static int COl = 3;
  
static List []indices = new List[MAX];
  
// All possible solutions of the
// equation 1/a + 1/b + 1/c = 1
static int [,]test = { { 2, 3, 6 }, { 2, 4, 4 },
                       { 2, 6, 3 }, { 3, 2, 6 },
                       { 3, 3, 3 }, { 3, 6, 2 },
                       { 4, 2, 4 }, { 4, 4, 2 },
                       { 6, 2, 3 }, { 6, 3, 2 } };
  
// Function to find the triplets
static int find_triplet(int []array, int n)
{
    int answer = 0;
    for (int i = 0; i < MAX; i++)
    {
        indices[i] = new List();
    }
      
    // Storing indices of the elements
    for (int i = 0; i < n; i++)
    {
        indices[array[i]].Add(i);
    }
  
    for (int i = 0; i < n; i++)
    {
        int y = array[i];
  
        for (int j = 0; j < ROW; j++) 
        {
            int s = test[j, 1] * y;
  
            // Check if y can act as the middle
            // element of triplet with the given
            // solution of 1/a + 1/b + 1/c = 1
            if (s % test[j, 0] != 0)
                continue;
            if (s % test[j, 2] != 0)
                continue;
  
            int x = s / test[j, 0];
            int z = s / test[j, 2];
            if (x > MAX || z > MAX)
                continue;
  
            int l = 0;
            int r = indices[x].Count - 1;
  
            int first = -1;
  
            // Binary search to find the number of
            // possible values of the first element
            while (l <= r)
            {
                int m = (l + r) / 2;
  
                if (indices[x][m] < i)
                {
                    first = m;
                    l = m + 1;
                }
                else
                {
                    r = m - 1;
                }
            }
  
            l = 0;
            r = indices[z].Count - 1;
  
            int third = -1;
  
            // Binary search to find the number of
            // possible values of the third element
            while (l <= r) 
            {
                int m = (l + r) / 2;
  
                if (indices[z][m] > i) 
                {
                    third = m;
                    r = m - 1;
                }
                else
                {
                    l = m + 1;
                }
            }
  
            if (first != -1 && third != -1) 
            {
  
                // Contribution to the answer would
                // be the multiplication of the possible
                // values for the first and the third element
                answer += (first + 1) * (indices[z].Count - third);
            }
        }
    }
    return answer;
}
  
// Driver code
public static void Main(String []args) 
{
    int []array = { 2, 4, 5, 6, 7 };
    int n = array.Length;
  
    Console.WriteLine(find_triplet(array, n));
}
}
  
// This code is contributed by Rajput-Ji


输出:
1