题目链接
思路
四个木棒拼出等边三角形,必定有两个木棒长度相等且等于边长,另外两根长度之和为边长。
数据范围,可以用一个桶统计每种木棍的数量,将木棍按长度排序,去重后枚举每一种木棍,数量大于等于2的木棍可作为一组边长,将边长记为,内层循环再从小到大枚举小木棍,长度记为,那么另一根小木棍长度为,根据桶中的信息维护答案。
其他
思路简单,但是写组合数算阶乘的时候取模了,调了两天才过。其实不需要写一个完整的组合数函数,因为题目中只用到。除法不能随便取模。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
using namespace std;
const int N=1E5+3,M=5E3+3,mod=1E9+7;
typedef long long ll;
int n;
ll ans;
int a[N],t[M];
inline ll read()
{
ll ret=0;char ch=getchar();
while(ch<'0' || ch>'9')
ch=getchar();
while(ch>='0' && ch<='9')
{
ret=ret*10+ch-'0';
ch=getchar();
}
return ret;
}
inline ll fac(ll p)
{
ll ret=1;
rep(i,2,p)
{
ret=(ret*i);
}
return ret;
}
inline ll C(ll fir,ll sec)
{
ll ret=1;
ret*=fac(fir);
ret/=fac(sec);
ret/=fac(fir-sec);
return ret%mod;
}
int main()
{
// freopen("in.in","r",stdin);
n=read();
rep(i,1,n)
{
a[i]=read();
++t[a[i]];
}
sort(a+1,a+n+1);
int nn=unique(a+1,a+n+1)-a-1;
rep(i,1,nn)
{
ll cur=a[i];
if(t[cur]<2ll)
continue;
// ll ty=C(t[cur],2ll);
ll ty=t[cur]*(t[cur]-1)/2;
// cout<<"::::"<<ty<<endl;
rep(j,1,i-1)
{
ll op=cur-a[j];
if(a[j]>op)
break;
if(a[j]==op)
{
// ans=(ans+(t[a[j]]*(t[a[j]]-1)/2)%mod*ty)%mod;
ans=(ans+(C(t[a[j]],2ll)*ty)%mod)%mod;
break;
}
// ans=(ans+(((t[a[j]]*ty)%mod)*t[cur-a[j]])%mod)%mod;
ans=(ans+(((t[a[j]]*ty)%mod)*t[op])%mod)%mod;
}
// cout<<ans<<endl;
}
cout<<ans<<endl;
}