版权声明:喜欢请点个大拇指,感谢各位dalao。弱弱说下,转载要出处呦 https://blog.csdn.net/qq_35786326/article/details/84894420
题目:
分析:
对于情况
,我们先将所有数排序,然后枚举
作为图
中紫色的边,即上面三个边中最长的边,同时记录
存前
个数两两相加得
的方案数。再从
向后枚举
作为红色边来统计答案。
对于情况
,先将排好序的数组去重,然后枚举
作为图
中的红色边,从
向前枚举
作为紫色边,这样灰色边长度就是已知的,就能知道用这两种长度的木棍拼出红色边的方案数。这样再设一个
,记录用比
长的棍作紫色边的方案数,这样乘起来加到答案里就行了。
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<queue>
#define ll long long
using namespace std;
ll num[10000005],sum[10000005];
ll f[5005],g[5005],h[5005];
ll s[5005],a[5005];
ll n,ans;
void getfg(){
f[2]=g[3]=h[4]=1;
for(ll i=2;i<n;i++) f[i+1]=f[i]*(i+1)/(i-1);
for(ll i=3;i<n;i++) g[i+1]=g[i]*(i+1)/(i-2);
for(ll i=4;i<n;i++) h[i+1]=h[i]*(i+1)/(i-3);
}
int main()
{
freopen("yist.in","r",stdin);
freopen("yist.out","w",stdout);
scanf("%lld",&n);getfg();
for(ll i=1;i<=n;i++){
scanf("%lld",&s[i]);
num[s[i]]++;
}
sort(s+1,s+n+1);
for(ll i=1;i<=n;i++){
for(ll j=i+1;j<=n;j++)
if(num[s[j]]>=3){
ans+=sum[s[j]-s[i]]*g[num[s[j]]];
while(s[j+1]==s[j]) j++;
}
for(ll j=i-1;j>=1;j--)
if(s[i]+s[j]<=1e7) sum[s[i]+s[j]]++;
}
ll pans=ans;
n=unique(s+1,s+n+1)-s-1;
for(ll i=1;i<=n;i++)
if(num[s[i]]>=2){
ll cnt=0;
for(ll j=i-1;j>=1;j--){
if(s[i]-s[j]>s[j]) break;
if(s[i]-s[j]==s[j]) {ans+=(h[num[s[j]]]+f[num[s[j]]]*cnt)*f[num[s[i]]];break;}
ans+=(f[num[s[j]]]*f[num[s[i]-s[j]]]+num[s[j]]*num[s[i]-s[j]]*cnt)*f[num[s[i]]];
cnt+=num[s[j]]*num[s[i]-s[j]];
}
}
cout<<ans;
return 0;
}