Number of Parallelograms

CodeForces - 660D

You are given n points on a plane. All the points are distinct and no three of them lie on the same line. Find the number of parallelograms with the vertices at the given points.

Input

The first line of the input contains integer n (1 ≤ n ≤ 2000) — the number of points.

Each of the next n lines contains two integers (x**i, y**i) (0 ≤ x**i, y**i ≤ 109) — the coordinates of the i-th point.

Output

Print the only integer c — the number of parallelograms with the vertices at the given points.

Example

Input

40 11 01 12 0

Output

1

题意:

给你n个互不相同的点,且没3个点在一条直线上。

问你这n个点能组成多少个不同的平行四边形。

思路:

因为没3个点在一条直线上,所以不存在两个平行四边形的中心点(对角线的交点)在同一点。

所以我们可以n*n枚举任意两个点,把这两点当作一个平行四边行的对角线,计算他的中心,如果有其他线的中心也是这个点,那么这2个对角线的4个点可以构成一个平行四边形。

我们可以用map来维护每一个中点出现的个数,依次计算出答案。

ps:因为计算两个点的中点过程中/2这一步会出现小数,所以我没/2,而是直接默认全是中点坐标是*2的。不影响答案的计算。

如果不保证三点共线就不能这样做,

因为会有这种情况:

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}

inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/

struct point {
    int x, y;
    point()
    {

    }
    point (int _x, int _y)
    {
        x = _x;
        y = _y;

    }
    point operator - (const point &b) const
    {
        return point(x - b.x, y - b.y);
    }
    point operator + (const point &b) const
    {
        return point(x + b.x, y + b.y);
    }
    bool operator < (const point &b) const
    {
        pii t1 = mp(x, y);
        pii t2 = mp(b.x, b.y);
        return t1 < t2;
    }
    void P()
    {
        cout << x << " " << y << endl;
    }
};

map<point, int> m;
point a[maxn];
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    int n;
    gbtb;
    cin >> n;
    repd(i, 1, n) {
        cin >> a[i].x >> a[i].y;
    }
    point v;
    int ans = 0;
    repd(i, 1, n) {
        repd(j, i + 1, n) {
            v = a[i] + a[j];
            ans += m[v];
            m[v]++;
        }
    }
    cout << ans  << endl;
    return 0;
}

inline void getInt(int *p)
{
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    } else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}