题目链接: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; }