//枚举 + HASH //和2002很像,这次是找平行四边形,规模1000,因此只能采用O(N^2) //一开始我是想到枚举3个点确定2条边,由这2条边确定第4的点,再用HASH判断是否存在,但是O(n^3)绝对TLE //再想了一下,发现可以枚举对角线,进而确定中点,2条直线如果中点相同,那么必定确定一个平行四边形 //根据这个性质来对边的中点值进行HASH就可以了,发现一个中点值就插入,并计数,最后答案就是这些计数的总和 //效率的关键是HASH函数的设计,我用折叠法的HASH随便搞了一通,再随便确定一个MAXHASH,结果居然有766MS //刷到第一版,哈哈! #include<iostream> using namespace std; const int MAXHASH = 7345787; int head[MAXHASH],next[1000003]; int m,ans; struct coord { long x,y; }P[1005]; struct midPoint { long x,y,cnt;//cnt计算出现的次数 }G[1000003]; int hash(int x,int y)//拿折叠法的HASH乱改了一下。。。 { int h = 0; h = ((x<<2) + (x>>4)) ^ (y<<10); h = h % MAXHASH; h = h < 0 ? h + MAXHASH : h; return h; } void insert(int x,int y) { int h = hash(x,y); bool Find = 0; for(int e = head[h];e != -1;e = next[e]) { if(G[e].x == x && G[e].y == y) { Find = 1; ans += G[e].cnt++; break; } } if(!Find) { G[m].x = x; G[m].y = y; G[m].cnt = 1; next[m] = head[h]; head[h] = m++; } } int main() { //freopen("in.txt","r",stdin); int t,n,x,y; scanf("%d",&t); while(t--) { scanf("%d",&n); memset(head,-1,sizeof(head)); memset(G,0,sizeof(G)); m = ans = 0; for(int i = 0;i < n;++i) scanf("%ld%ld",&P[i].x,&P[i].y); for(int i = 0;i < n;++i) for(int j = i + 1;j < n;++j)//枚举边 insert(P[i].x + P[j].x,P[i].y + P[j].y); printf("%d/n",ans); } return 0; }