【NOI2017模擬5.31】diyiti
阿新 • • 發佈:2018-12-16
Description
給定n 根直的木棍,要從中選出6 根木棍,滿足:能用這6 根木棍拼出一個正方形。注意木棍不能彎折。問方案數。
正方形:四條邊都相等、四個角都是直角的四邊形。
Input
第一行一個整數n。
第二行包含n 個整數ai,代表每根木棍的長度。
8
4 5 1 5 1 9 4 5
Output
一行一個整數,代表方案數。
3
桶預處理+n^2實現
分類討論
2 2 1 1 和 3 1 1 1 (數字表示每條邊要用到的木棍數)
首先,1即邊長是一定要列舉的
2 2 1 1:
2的話我們可以分四種情況討論:(列舉a)
1:a+a a+a
直接判a*2時候等於邊長然後做就可以了
2:a+a b+c
這兒就要用到f陣列了(f[i]表示兩個木棒組成的長度為i的方案數)
因為f[i]還包含了a+a的情況,所以減去即可
3:a+b a+b
有了a,便可以得到b了
然後判斷一下a,b是否都有兩個以上
有的話便加到答案裡。
4:a+b c+d
這個嘛,就又要用到f陣列了
f[邊長]記得減去a+b的方案數即可
對了,還有減去c=d的情況哦,哦,哦
3 1 1 1:
3的話我們就不用分情況了
先列舉其中的一條邊,然後用f陣列得出另外兩條的方案數即可
還要減去兩個相等的情況
記得特判三個都相等的情況
下面貼程式碼:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,a[5010],b[5010][2],tot=1,cnt=0;
int c[10000001],d[20000001];
ll ans=0,s,ww;
inline int read()
{
int x=0; char c=getchar();
while (c<'0' || c>'9') c=getchar();
while (c>='0' && c<='9') x=(x<<1)+(x<< 3)+(c^48),c=getchar();
return x;
}
int main()
{
freopen("yist.in","r",stdin);
freopen("yist.out","w",stdout);
n=read();
for (int i=1;i<=n;i++)
{
a[i]=read();c[a[i]]++;
for (int j=1;j<i;j++) d[a[i]+a[j]]++;
}
sort(a+1,a+n+1);
b[tot][0]=a[1],b[tot][1]=1;
for (int i=2;i<=n;i++)
{
if (a[i]==a[i-1]) b[tot][1]++;
else b[++tot][0]=a[i],b[tot][1]=1;
}
for (int i=1,k;i<=tot;i++)
{
if (b[i][1]>=2) // 2 2 1 1
{
s=0;k=0;ww=b[i][1]*(b[i][1]-1)>>1;
if (b[i][0]%2==0) k=(c[b[i][0]>>1])*(c[b[i][0]>>1]-1)>>1;
for (int j=1;(b[j][0]<<1)<=b[i][0];j++)
if ((b[j][0]<<1)==b[i][0])
{
//a a & a a
if (b[j][1]>=4) ans+=ww*b[j][1]*(b[j][1]-1)*(b[j][1]-2)*(b[j][1]-3)/24;
//a a & b c
if (b[j][1]>=2) ans+=ww*b[j][1]*(b[j][1]-1)*(d[b[i][0]]-(b[j][1]*(b[j][1]-1)>>1))>>1;
}
else
{
int mid=c[b[i][0]-b[j][0]];
//a b & a b
if (b[j][1]>=2 && mid>=2)
ans+=ww*b[j][1]*(b[j][1]-1)*mid*(mid-1)>>2;
//a b & c d
s+=ww*b[j][1]*mid*(d[b[i][0]]-b[j][1]*mid-k);
}
ans+=(s>>1);
}
if (b[i][1]>=3) // 3 1 1 1
{
s=0;ww=b[i][1]*(b[i][1]-1)*(b[i][1]-2)/6;
for (int j=1;a[j]<b[i][0];j++)
{
int mid=b[i][0]-a[j];
//a a a
if (a[j]*3==b[i][0]) s+=ww*(d[mid]-c[mid-a[j]]+1);
else if (mid>a[j]) s+=ww*(d[mid]-c[mid-a[j]]);
else s+=ww*d[mid];
}
ans+=s/3;
}
}
printf("%lld\n",ans);
return 0;
}