1. 程式人生 > >bzoj 4927: 第一題

bzoj 4927: 第一題

四邊形 || clu nbsp blog round des urn log

Description

給定n根直的木棍,要從中選出6根木棍,滿足:能用這6根木棍拼 出一個正方形。註意木棍不能彎折。問方案數。 正方形:四條邊都相等、四個角都是直角的四邊形。

Input

第一行一個整數n。 第二行包含n個整數ai,代表每根木棍的長度。 n ≤ 5000, 1 ≤ ai ≤ 10^7

Output

一行一個整數,代表方案數。 考慮正方形每條邊由幾條木棍組成,只有1122和1113兩種情況,分別枚舉統計一下
#include<bits/stdc++.h>
typedef long long i64;
int
n,a[5007],ap=0,as[5007],at[5007],t[10000007]; i64 ans=0,c3[5007]; int main(){ scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%d",a+i); std::sort(a+1,a+n+1); for(int i=1,j=1;i<=n;i=j){ int x=a[i]; for(;j<=n&&a[j]==x;++j); c3[ap]=i64(j-i)*(j-i-1)*(j-i-2
)/6; as[ap]=x; at[ap++]=j-i; } for(int i=1;i<=n;++i){ for(int j=0;j<ap;++j)if(as[j]>a[i]){ ans+=c3[j]*t[as[j]-a[i]]; } for(int j=1;j<i&&a[i]+a[j]<=10000000;++j)++t[a[i]+a[j]]; } for(int i=0,l,r;i<ap;++i)if(at[i]>=2
){ i64 s=0,s0=0,s1; for(r=i-1,l=0;r>=l;--r){ for(;r>=l&&as[l]+as[r]<as[i];++l); if(r<l||as[l]+as[r]!=as[i])continue; int x=at[l]; if(r==l){ s1=x*(x-1)/2; s+=s1*(x-2)*(x-3)/12; }else{ int y=at[r]; s1=x*y; s+=s1*(x-1)*(y-1)/4; } s+=s0*s1; s0+=s1; } ans+=at[i]*(at[i]-1)/2*s; } printf("%lld\n",ans); return 0; }

bzoj 4927: 第一題