Как найти количество параллелограмма

Given some points on a plane, which are distinct and no three of them lie on the same line. We need to find number of Parallelograms with the vertices as the given points. Examples:

Input : points[] = {(0, 0), (0, 2), (2, 2), (4, 2), 
                                   (1, 4), (3, 4)}
Output : 2
Two Parallelograms are possible by choosing above
given point as vertices, which are shown in below 
diagram.

We can solve this problem by using a special property of parallelograms that diagonals of a parallelogram intersect each other in the middle. So if we get such a middle point which is middle point of more than one line segment, then we can conclude that a parallelogram exists, more accurately if a middle point occurs x times, then diagonals of possible parallelograms can be chosen in xC2 ways, i.e. there will be x*(x-1)/2 parallelograms corresponding to this particular middle point with a frequency x. So we iterate over all pair of points and we calculate their middle point and increase frequency of middle point by 1. At the end, we count number of parallelograms according to the frequency of each distinct middle point as explained above. As we just need frequency of middle point, division by 2 is ignored while calculating middle point for simplicity. 

CPP

#include <bits/stdc++.h>

using namespace std;

int countOfParallelograms(int x[], int y[], int N)

{

    map<pair<int, int>, int> cnt;

    for (int i=0; i<N; i++)

    {

        for (int j=i+1; j<N; j++)

        {

            int midX = x[i] + x[j];

            int midY = y[i] + y[j];

            cnt[make_pair(midX, midY)]++;

        }

    }

    int res = 0;

    for (auto it = cnt.begin(); it != cnt.end(); it++)

    {

        int freq = it->second;

        res += freq*(freq - 1)/2;

    }

    return res;

}

int main()

{

    int x[] = {0, 0, 2, 4, 1, 3};

    int y[] = {0, 2, 2, 2, 4, 4};

    int N = sizeof(x) / sizeof(int);

    cout << countOfParallelograms(x, y, N) << endl;

    return 0;

}

Java

import java.io.*;

import java.util.*;

public class GFG {

    public static int countOfParallelograms(int[] x, int[] y, int N)

    {

        HashMap<String, Integer> cnt = new HashMap<>();

        for (int i=0; i<N; i++)

        {

            for (int j=i+1; j<N; j++)

            {

                int midX = x[i] + x[j];

                int midY = y[i] + y[j];

                String temp = String.join(" ", String.valueOf(midX), String.valueOf(midY));

                if(cnt.containsKey(temp)){

                    cnt.put(temp, cnt.get(temp) + 1);

                }

                else{

                    cnt.put(temp, 1);

                }

            }

        }

        int res = 0;

        for (Map.Entry<String, Integer> it : cnt.entrySet()) {

            int freq = it.getValue();

            res = res + freq*(freq - 1)/2;

        }

        return res;

    }

    public static void main(String[] args) {

        int[] x = {0, 0, 2, 4, 1, 3};

        int[] y = {0, 2, 2, 2, 4, 4};

        int N = x.length;

        System.out.println(countOfParallelograms(x, y, N));

    }

}

Python3

def countOfParallelograms(x, y, N):

    cnt = {}

    for i in range(N):

        for j in range(i+1, N):

            midX = x[i] + x[j];

            midY = y[i] + y[j];

            if ((midX, midY) in cnt):

                cnt[(midX, midY)] += 1

            else:

                cnt[(midX, midY)] = 1

    res = 0

    for key in cnt:

        freq = cnt[key]

        res += freq*(freq - 1)/2

    return res

x = [0, 0, 2, 4, 1, 3]

y = [0, 2, 2, 2, 4, 4]

N = len(x);

print(int(countOfParallelograms(x, y, N)))

C#

using System;

using System.Collections.Generic;

public class GFG

{

  public static int CountOfParallelograms(int[] x, int[] y, int N)

  {

    Dictionary<string, int> cnt = new Dictionary<string, int>();

    for (int i = 0; i < N; i++)

    {

      for (int j = i + 1; j < N; j++)

      {

        int midX = x[i] + x[j];

        int midY = y[i] + y[j];

        string temp = string.Join(" ", midX.ToString(), midY.ToString());

        if (cnt.ContainsKey(temp))

        {

          cnt[temp]++;

        }

        else

        {

          cnt.Add(temp, 1);

        }

      }

    }

    int res = 0;

    foreach (KeyValuePair<string, int> it in cnt)

    {

      int freq = it.Value;

      res += freq * (freq - 1) / 2;

    }

    return res;

  }

  public static void Main(string[] args)

  {

    int[] x = { 0, 0, 2, 4, 1, 3 };

    int[] y = { 0, 2, 2, 2, 4, 4 };

    int N = x.Length;

    Console.WriteLine(CountOfParallelograms(x, y, N));

  }

}

Javascript

function countOfParallelograms(x, y, N)

{

    let cnt = new Map();

    for (let i=0; i<N; i++)

    {

        for (let j=i+1; j<N; j++)

        {

            let midX = x[i] + x[j];

            let midY = y[i] + y[j];

            let make_pair = [midX, midY];

            if(cnt.has(make_pair.join(''))){

                cnt.set(make_pair.join(''), cnt.get(make_pair.join('')) + 1);

            }

            else{

                cnt.set(make_pair.join(''), 1);

            }

        }

    }

    let res = 0;

    for (const [key, value] of cnt)

    {

        let freq = value;

        res = res + Math.floor(freq*(freq - 1)/2);

    }

    return res;

}

let x = [0, 0, 2, 4, 1, 3];

let y = [0, 2, 2, 2, 4, 4];

let N = x.length;

console.log(countOfParallelograms(x, y, N));

Time Complexity: O(n2logn), as we are iterating through two loops up to n and using a map as well which takes logn.
Auxiliary Space: O(n)

This article is contributed by Utkarsh Trivedi. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Last Updated :
16 Feb, 2023

Like Article

Save Article

На координатной плоскости рисуют параллелограмм OABC, у которого центр находится в точке (19/2, 15/2), а точки A, B и C имеют натуральные координаты. Найдите количество таких параллелограммов. (Здесь через O обозначено начало координат — точка (0,0); два параллелограмма с одинаковым набором вершин считаются одинаковыми, т.е. OABC и OCBA считаем одним и тем же параллелограммом.

Так как координаты центра параллелограммов не меняются и одна вершина должна находиться в начале координат, то и координаты точки В не должны меняться. Хв=2*9,5=19 и Ув=7,5*2=15. Значит могут меняться координаты только точек А и С. Какими же они могут быть. Только натуральными. Остается посчитать количество таких точек. По условию (Ха+Хс)/2=9,5 или Ха+Хс=19. Аналогично (Уа+Ус)/2=7,5 или Уа+Ус=15. Хс может меняться от 0 до 7, а Ха соответственно от 19 до 8. Значит всего можно построить 8 параллелограммов.

автор вопроса выбрал этот ответ лучшим

Знаете ответ?

Смотрите также:

Какие ответы на олимпиаду ВсОШ математика 10 класс 21 октября 2022 (гр. 4)?

Какие ответы на олимпиаду ВсОШ математика 10 класс 20 октября 2022 (гр. 3)?

Какие ответы на олимпиаду ВсОШ математика 10 класс 19 октября 2022 (гр. 2)?

ВПР по математике 4 класс 2021, задания, ответы, демоверсии, где найти?

ВПР по математике 5 класс 2021, задания, ответы, демоверсии, где найти?

Какого числа будет проводится экзамен по математике в 10 классах?

ВПР математика 5 класс. Как решить задачу про площади материков?

ВПР математика 5 класс. Как решить задачу про Олю и пакетик орехов?

ВПР по математике 6 класс 2021, задания, ответы, демоверсии, где найти?

ВПР по математике 8 класс 2021, задания, ответы, демоверсии, где найти?

Вам заданы n точек на плоскости. Никакая пара точек не совпадает, никакие три точки не лежат на одной прямой. Найдите количество параллелограммов с вершинами в заданных точках.

Входные данные

В первой строке находится целое число n (1 ≤ n ≤ 2000) — количество точек.

В следующих n строках находятся пары целых чисел (xi, yi) (0 ≤ xi, yi ≤ 109) — координаты i-й точки.

Выходные данные

Выведите одно целое число c — количество параллелограммов с вершинами в заданных точках.

Пример

Входные данные

4
0 1
1 0
1 1
2 0

Доброго времени суток, уважаемые соучастники!
Набрела на задачу:
Параллелограмм пересекается двумя рядами прямых, параллельных его сторонам; каждый ряд состоит из m прямых. Сколько параллелограммов можно выделить в образовавшейся сетке?

По-идее задача должна как-то решаться при помощи числа сочетаний, но я не могу понять с какой стороны тут начать. Подкиньте идею решения, пожалуйста.
Спасибо за внимание.
С уважением, Светлана.

UPD: ответ [math]left(frac{(m+1)(m+2)}{2}right)^2[/math]

Я должен решить проблему, когда, учитывая размер сетки N x M, я должен найти количество параллелограммов, которые «могут быть помещены в него» таким образом, чтобы каждая их координата была целым числом.

Вот мой код:

/*
~Keep It Simple!~
*/

#include<fstream>

#define MaxN 2005

int N,M;
long long Paras[MaxN][MaxN]; // Number of parallelograms of Height i and Width j
long long Rects; // Final Number of Parallelograms

int cmmdc(int a,int b)
{
while(b)
{
int aux = b;
b = a -(( a/b ) * b);
a = aux;
}

return a;
}

int main()
{
freopen("paralelograme.in","r",stdin);
freopen("paralelograme.out","w",stdout);

scanf("%d%d",&N,&M);

for(int i=2; i<=N+1; i++)
for(int j=2; j<=M+1; j++)
{
if(!Paras[i][j])
Paras[i][j] = Paras[j][i] = 1LL*(i-2)*(j-2) + i*j - cmmdc(i-1,j-1) -2; // number of parallelograms with all edges on the grid + number of parallelograms with only 2 edges on the grid.
Rects += 1LL*(M-j+2)*(N-i+2) * Paras[j][i]; // each parallelogram can be moved in (M-j+2)(N-i+2) places.
}

printf("%lld", Rects);
}

Пример: для сетки 2×2 у нас есть 22 возможных параллелограмма.

Мой алгоритм работает, и он правильный, но мне нужно сделать его немного быстрее. Я хочу знать, как это возможно.

Постскриптум Я слышал, что я должен предварительно обработать наибольший общий делитель и сохранить его в массиве, который сократит время выполнения до O (n * m), но я не уверен, как это сделать без использования cmmdc ( наибольший общий делитель) функция.

1

Решение

Убедитесь, что N не меньше, чем M:

if( N < M ){ swap( N, M ); }

Используйте симметрию в своих циклах, вам нужно всего лишь запустить j от 2 до i:

for(int j=2; j<=min( i, M+1); j++)

вам не нужен дополнительный массив Paras, брось это. Вместо этого используйте временную переменную.

long long temparas = 1LL*(i-2)*(j-2) + i*j - cmmdc(i-1,j-1) -2;
long long t1 = temparas * (M-j+2)*(N-i+2);
Rects += t1;
// check if the inverse case i <-> j must be considered
if( i != j && i <= M+1 ) // j <= N+1 is always true because of j <= i <= N+1
Rects += t1;

Заменить эту строку: b = a -(( a/b ) * b); используя оператор остатка:

b = a % b;

Возможно, было бы возможно кэширование результатов cmmdc. Вы можете инициализировать массив с помощью алгоритма сортировки: создайте двумерный массив, индексированный с помощью a и b, поставьте «2» в каждой позиции, где a и b кратны 2, а затем поставьте « 3 «в каждой позиции, где a и b кратны 3, и так далее, примерно так:

int gcd_cache[N][N];

void init_cache(){
for (int u = 1; u < N; ++u){
for (int i = u; i < N; i+=u ) for (int k = u; k < N ; k+=u ){
gcd_cache[i][k] = u;
}
}
}

Не уверен, что это сильно поможет.

0

Другие решения

Первый комментарий в вашем коде гласит: «будь проще», поэтому, в свете этого, почему бы не попытаться решить проблему математически и распечатать результат.

Если вы выберете две линии длины N из вашей сетки, вы найдете количество параллелограммов следующим образом:

  • Выберите две точки рядом друг с другом в обеих строках: есть (N-1)^2
    способы сделать это, так как вы можете расположить две точки на N-1
    позиции на каждой из линий.
  • Выберите две точки с одним пробелом между ними в обеих линиях: есть (N-2)^2 способы сделать это.
  • Выберите две точки с двумя, тремя и до N-2 пробелы между ними.
  • Итоговое количество комбинаций будет (N-1)^2+(N-2)^2+(N-3)^2+...+1,
  • Решив сумму, мы получим формулу: 1/6*N*(2*N^2-3*N+1), Проверьте Вольфрам Альфа проверять.

Теперь, когда у вас есть решение для двух строк, вам просто нужно умножить его на число комбинации порядка 2 М, который является M!/(2*(M-2)!),

Таким образом, вся формула будет: 1/12*N*(2*N^2-3*N+1)*M!/(M-2)!, где ! знак обозначает факториал, и ^ обозначает оператор степени (обратите внимание, что тот же знак не является оператором степени в C ++, но побитовый XOR оператор).

Этот расчет требует меньше операций, чем итерация по матрице.

0

Понравилась статья? Поделить с друзьями:
  • Как найти бпм сэмпла
  • Предметов после того как ты их найдешь
  • Как найти глядящего в небо
  • No gulpfile found как исправить
  • Как найти инн по серии паспорта