给定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 。
例子:
Input: arr[] = {2, 4, 5, 6, 7}
Output: 1
Only possible triplet is {2, 4, 6}
Input: arr[] = {4, 4, 4, 4, 4}
Output: 10
方法:
- 请考虑以下方程式:
L = a * arr[i], L = b * arr[j] and L = c * arr[k].
Thus, arr[i] = L / a, arr[j] = L / b and arr[k] = L / c.
So, using this in arr[i] + arr[j] + arr[k] = L gives L / a + L / b + L / c = L
or 1 / a + 1 / b + 1 / c = 1.
Now, there can only be 10 possible solutions of the above equation, which are
{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}All possible triplets (arr[i], arr[j], arr[k]) will satisfy these solutions. So, all these solutions can be stored in a 2D array say test[][3]. So, that all the triplets which satisfy these solutions can be found.
- 对于从1到N的所有i 。考虑将arr [i]作为三元组的中间元素。并找到等式1 / a + 1 / b + 1 / c = 1的所有可能解的三元组的相应第一和第三元素。找到所有情况的答案,并将它们添加到最终答案中。
- 保持数组中出现arr [i]的索引。对于给定的等式X的可能解,对于每个数字arr [i]保持该数字作为三元组的中间元素,并找到第一个和第三个元素。对第一个和第三个元素的可用索引集进行二进制搜索,以查找第一个元素的出现次数从1到i – 1以及第三个元素的出现次数从i + 1到N。将两个值相乘并将其添加到最终答案中。
下面是上述方法的实现:
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