题目链接:https://ac.nowcoder.com/acm/contest/52441/F

小白月赛的hard难度,数据量是3000个点。

在这里有些地方比赛的时候想到了,但是没有想到能够很好具体实现的方法,尤其是在共线那里。

easy不用说了,比赛的时候直接暴力过。

hard难度的,我们可以先枚举一个顶点,然后枚举这个点到其他各点的距离(这里是比赛的时候能够想到的地方),然后组成的三角形就是相同数量点的n*(n-1)/2,这里直接累加之前匹配的也是可以的,因为这本身就是一个求和函数,这里也是很容易就可以匹配出来的。那么共线情况如何处理?

如果存在两边相等的共线,我们自然可以通过(xa+xb)/2 , (ya+yb)/2计算出来,这是非常容易的。
然后这个公式随便移项一下就可以得到另一个可能共线的点,看这个点是否存在就ok。
那么我们就需要hash一下点(重点)因为点可能存在负数,所以我们需要都移动到正象限。
对于共线的点,我们直接记录一下,最后答案-点数/2. 为什么是要减去这么一个数,因为如果存在共线,那么必然在一个等腰三角形中被记录两次。

对于一个直角坐标系中,不存在除了正四边形之外的正多边形这么一个定理,我们可以直接排除掉等边三角形的情况。故 - linecnt/2;

总结一下:这个题并不算难,可能共线问题想的有点多,虽然知道不存在等边三角形但是还是没有联系起来,另外移动象限也是想不到的,自己需要提升的地方还有很多。

code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define cyes cout<<"YES\n"
#define cno cout<<"NO\n"
#define calice cout<<"Alice\n"
#define cbob cout<<"Bob\n"
#define mem(a) memset((a),0,sizeof (a))
#define fi first
#define se second
#define debug(x) cout << #x << ": " << x << endl
#define ii pair<ll,ll>
#define lb lower_bound
#define ub upper_bound
#define nxtper next_permutation
#define cmpmax greater<int>()
#define upchu(a,b) (((a)/(b))+!!((a)%(b)))
#define all(x) x.begin(), x.end()
#define eback emplace_back
#define is_out(x) ((double)clock()/CLOCKS_PER_SEC<=x)
//#pragma GCC optimize(2)

const int mod7 = 1e9+7;
const int mod9 = 998244353;
const int INF = 1e9;
const ll LNF = 1e18;
const double eps = 1e-4;
int fx[4] = {-1,0,1,0};
int fy[4] = {0,-1,0,1};


const int nn = 3010;
int cnt[2000000];
int x[nn],y[nn],vis[nn][nn];
int juli(int i,int j){
	return (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
}
int main()
{
 	//cin.ignore(numeric_limits<streamsize>::max(),'\n');
	ios_base::sync_with_stdio(0); cin.tie(0); //cout.tie(0);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x[i]>>y[i];
		vis[x[i]+1500][y[i]+1500] = 1;
	}
	ll ans = 0;
	ll line = 0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i==j) continue;
			int dis = juli(i,j);
			ans+=cnt[dis];
			cnt[dis]++;
			if(vis[2*x[i]-x[j]+1500][2*y[i]-y[j]+1500]==1) line++;
		}
		for(int j=1;j<=n;j++){
			if(i==j) continue;
			cnt[juli(i,j)] = 0;
		}
	}
	cout<<ans-line/2;
}