思路
在不考虑能否构成三角形的情况下,三角形有这几种情况:
- 三条边的长度各不相等;
- 等腰,其中腰比底长;
- 等腰,其中底比腰长;
- 等边三角形。
题目中木棍的长度都是 2 的幂,我们再对上述几种情况作进一步分析:
- 无法构成三角形。为了构成三角形,我们要让较短的 2 条木棍尽量长,则三个木棍的长度为 2x,2x+1,2x+2,明显构不成三角形。
- 很明显可以构成三角形。
- 无法构成三角形。两条腰长度之和最大也只能等于底。
- 很明显可以构成三角形。
实现
经分析只有下面 2 种三角形:
- 等腰,其中腰比底长;
- 等边三角形。
于是这么做:
首先桶排,因为 ai≤n,所以可以桶排。
设长度为 2x 的木棍有 bx 根,则上述两种三角形的方案数分别为:
- ∑x=1n(Cbx2×∑i=1x−1bx)
- ∑x=1n(Cbx3)
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include<iostream> #include<algorithm> #include<cstring> #define int long long
using namespace std;
int t,n,ans; int a[300002],b[300002],c[300002];
//a 是每个木棍的长度 //b 是桶 //c 是 b 的前缀和
signed main(){ cin>>t; while(t--){ ans=0; memset(b,0,sizeof(b)); cin>>n; for(int i=1;i<=n;++i){ cin>>a[i]; ++b[a[i]]; } c[0]=b[0]; for(int i=0;i<=n;++i){ if(i>0) c[i]=c[i-1]+b[i]; if(b[i]>=2&&i>0) ans+=b[i]*(b[i]-1)/2*c[i-1];//1 类三角形的方案数 if(b[i]>=3) ans+=b[i]*(b[i]-1)*(b[i]-2)/6;//2 类三角形的方案数 } cout<<ans<<endl; } }
|