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