T1
题解
一共要使用六根木棍,那么分割的方法就两种{1,1,1,3},{1,1,2,2}
那么关键就是要计算2,3的数量。
cnt1[i]表示每种长度的木棍的方案数
cnt2[i]最初表示用不同的木棍拼成长度为i边的方案数,后来表示选出四根木棍构成{2,2}的方案数。
cnt22[i]表示用两个长度相同的不同木棍拼成长度为i的边的方案数。
cnt3[i]表示用三根不同的木棍拼成长度为i的方案数。
考虑两个的情况,我们可以
关键是怎么求cnt3,cnt2.
(1)cnt3
考虑cnt3的组成枚举cnt1超过3的长度sum,然后枚举每一根单独的木棍,设长度为x。
因为cnt2中保证了两个木棍是不同的,所以只需要考虑减去枚举到的木棍计入了cnt2的情况,不合法的情况就是cnt1[sum-2*x]。还有一种特殊情况需要注意
这样计算相当于(x,y,z)三元组在枚举到x,y,z的时候都会计算一遍。所以最后的和要/3
(2)cnt2
组成情况比较复杂,首先枚举两根木棍形成的长度
1.先考虑最简单的,选中的四根木棍的长度相同,贡献是
2.(x,y,z,z)这种情况也比较好计算,答案是是
会不会出现(x,z,z,z),不会啊如果那样的话x=z,同第一种情况
3.(x,y,x,y)中情况等价于从
4.(x,y,z,k)我们枚举sum=x+y,枚举x(这里枚举的是长度,不再是木棍)。可以确定二元组(x,y)。要求(z,k)与(x,y)不同且z!=k。答案是
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 10000003
#define LL long long
#define M 100003
using namespace std;
int n,a[M];
LL cnt1[N],cnt2[N],cnt22[N],cnt3[N],C1[N];
int q[M],m,q1[M],m1;
LL C(int x,int y)
{
if (y>x) return 0;
LL t=1;
for (int i=x-y+1;i<=x;i++) t*=(LL)i;
for (int i=1;i<=y;i++) t/=(LL)i;
return t;
}
int main()
{
freopen("yist.in","r",stdin);
freopen("yist.out","w",stdout);
scanf("%d",&n);
int mx=0;
for (int i=1;i<=n;i++) {
scanf("%d",&a[i]),cnt1[a[i]]++;
mx=max(mx,a[i]);
}
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
if (a[i]+a[j]<=mx) {
cnt2[a[i]+a[j]]++;
if (a[i]==a[j]) cnt22[a[i]+a[j]]++;
}
for (int i=1;i<=mx;i++) C1[i]=C(cnt1[i],2);
for (int i=1;i<=mx;i++)
if (cnt1[i]>=3) q[++m]=i;
for (int i=1;i<=mx;i++)
if (cnt1[i]) q1[++m1]=i;
for (int i=1;i<=m;i++) {
int sum=q[i]; LL cnt=0;
for (int j=1;j<=n;j++) {
if (a[j]>=sum) continue;
int x=a[j];
if (x*3!=sum)
cnt+=(LL)(cnt2[sum-x]-(sum-2*x>0?cnt1[sum-2*x]:0));
else cnt+=(LL)(cnt2[sum-x]-(sum-2*x>0?cnt1[sum-2*x]-1:0));
}
cnt3[sum]+=(LL)cnt/3;
}
m=0;
for (int i=1;i<=mx;i++)
if(cnt1[i]>=2) q[++m]=i;
for (int i=1;i<=m;i++) {
int x=q[i];
LL t=cnt2[x]-cnt22[x];
cnt2[x]=0; LL sum=0;
for (int j=1;j<=m1;j++) {
if (q1[j]*2==x||q1[j]>x-q1[j]) continue;
cnt2[x]+=C1[q1[j]]*C1[x-q1[j]];
sum+=(LL)(t-cnt1[q1[j]]*cnt1[x-q1[j]])*cnt1[q1[j]]*cnt1[x-q1[j]];
}
cnt2[x]+=sum/2;
if (x*2%4==0) cnt2[x]+=C(cnt1[x*2/4],4);
cnt2[x]+=(LL)cnt22[x]*t;
}
LL ans=0;
for (int i=1;i<=m1;i++){
int x=q1[i];
if (cnt1[x]<2) continue;
ans+=C(cnt1[x],3)*cnt3[x];
ans+=C1[x]*cnt2[x];
}
printf("%I64d\n",ans);
}