题目描述
解决过程
暴力不多阐述,很显然是无法AC的
解决此题需要用到组合数
思路
这道题要求拼成等边三角形,我们设三边长为 a , b , c a ,b ,c a,b,c 则 a = b = c a = b = c a=b=c ,
由于是用四根拼成,那么其中必有两条边相等,在此我们设 a = b a = b a=b , c = i + j c = i+j c=i+j,把数据存到桶里面,桶为 f f f
那么需要 f [ c ] > = 2 f[c] >= 2 f[c]>=2,此时如果 i = j = c / 2 i = j = c/2 i=j=c/2,根据组合数,那么新增的方案数为 C f [ i ] 2 ∗ C f [ c ] 2 C^2_{f[i]} * C^2_{f[c]} Cf[i]2∗Cf[c]2,
当 i ! = j i != j i!=j时,根据乘法原理和组合数,新增的方案数为 f [ i ] ∗ f [ j ] ∗ C f [ c ] 2 f[i] * f[j] * C^2_{f[c]} f[i]∗f[j]∗Cf[c]2
于是可以用 O ( n 2 ) O(n^2) O(n2) 的复杂度AC此题
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXM = 1e3 * 5 + 10;
const int mod = 1e9 + 7;
int a[MAXM] ,n ,ans = 0 ,s ,t;
int C (int nn, int mm) {
return nn * (nn - 1) >> 1;
}
int main () {
// freopen ("P3799_1.in","r",stdin);
// freopen ("P3799.out","w",stdout);
scanf ("%d",&n);
int x;
for (int q = 1;q <= n;++ q) {
scanf ("%d",&x);
s = min (s ,x);
t = max (t ,x);
a[x] ++;
}
for (int q = s;q <= t;++ q) {
if (a[q] > 1) {
for (int i = s;i <= q / 2;++ i) {
int j = q - i;
if (a[i] && a[j]) {
if (i != j) {
ans += a[i] * a[j] * C (a[q] ,2);
ans %= mod;
}
else if (i == j && a[j] >= 2) {
ans += C (a[q] ,2) * C (a[i] ,2);
ans %= mod;
}
}
}
}
}
printf ("%d\n",ans % mod);
return 0;
}
感想
谢谢大家
——2020.9.13