题意:小明在二维坐标系中放置了 n 个点,他想在其中选出一个包含三个点的子集,这三个点能组成三角形。然而这样的方案太多了,他决定只选择那些可以组成等腰三角形的方案。请帮他计算出一共有多少种选法可以组成等腰三角形?
思路:这个数据量肯定不能n^3暴力,所以很简单就是对于每个点求其他点到这个点的距离,然后根据分组计算组合数,但是要注意三点贡献,其他就是代码的事情。
反思:这么简单的题……我的代码写的非常有问题,不仅组合数计算错误,其实分组也没分好,而且很多关键性质也没发现,只能说一坨了,那么代码好好纠正,我觉得以后得一步步写,不要脑子一热就开始了,参考了题解,写的十分优美
参考题解:题解:P9423 [蓝桥杯 2023 国 B] 数三角 - 洛谷专栏
那么我自己的代码其实跟题解一毛一样:
#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define int128 __int128
#define endl '\n'
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
const int N = 2e5+10;
const int INF = 1e18;
const int MOD = 1e9+7;
int x[N],y[N];
map<int,map<int,int> > mp;
int cal(int a,int b){
return( (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
}
void solve(){
int n;
cin >> n;
for(int i=0;i<n;i++){
cin >> x[i] >> y[i];
mp[x[i]][y[i]]++;
}
int ans=0;
for(int i=0;i<n;i++){
map<int,int> cnt;
for(int j=0;j<n;j++){
ans+=cnt[cal(i,j)];
cnt[cal(i,j)]++;
}
for(int j=0;j<i;j++){
if(((x[j]+x[i])%2)==0 && ((y[j]+y[i])%2)==0){
ans-=mp[(x[j]+x[i])/2][(y[j]+y[i])/2];
}
}
}
cout << ans << endl;
}
signed main() {
IOS;
int t = 1;
// cin >> t;
while (t--) {
solve();
}
}
关了int long long,好像最后一个测试样例会爆。