感觉这类的题做多了还是有很明显的套路痕迹的。
给你一个
n
≤
2
e
3
n\leq2e3
n≤2e3个互不相同的点,然后求又多少个平行四边形。其实判定平行四边形的条件只需要两直线平行且相等。用一个map维护线段的斜率和长度。然后直接枚举所有的线段。
注意同一个平行四边形会被两个不同的邻边算两次,答案要除2。
时间复杂度
O
(
n
2
l
o
g
n
)
O(n^2logn)
O(n2logn)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=2e3+7;
map< pair< pair<ll,ll>,ll > ,int> mp;
struct Point {
int x,y;
Point() {}
Point(int x,int y):x(x),y(y) {}
}a[N];
ll sq(ll x) {
return x*x;
}
int main() {
int n;
ll ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
for(int i=1;i<=n;i++) {
for(int j=i+1;j<=n;j++) {
ll dis=sq(a[i].x-a[j].x)+sq(a[i].y-a[j].y);
if(a[i].x==a[j].x) {
ans+=mp[make_pair( make_pair(1,1e18), dis )];
mp[make_pair( make_pair(1,1e18), dis)]++;
}
else {
ll x=a[i].x-a[j].x;
ll y=a[i].y-a[j].y;
ll gcd=__gcd(x,y);
x/=gcd,y/=gcd;
if(x>0) {
ans+=mp[make_pair( make_pair(x,y),dis) ];
mp[make_pair( make_pair(x,y),dis) ]++;
}
else {
x=-x;
y=-y;
ans+=mp[make_pair( make_pair(x,y),dis) ];
mp[make_pair( make_pair(x,y),dis)]++;
}
}
}
}
printf("%lld\n",ans/2);
return 0;
}