-
- 53通过
- 345提交
- 题目提供者orangebird
- 标签
- 难度普及/提高-
- 时空限制1s / 128MB
提交 讨论 题解
最新讨论更多讨论
- 暂时没有讨论
题目背景
上道题中,妖梦斩了一地的木棒,现在她想要将木棒拼起来。
题目描述
有n根木棒,现在从中选4根,想要组成一个正三角形,问有几种选法?
输入输出格式
输入格式:
第一行一个整数n
第二行n个整数,a1,a2,……an(0<ai<=5000),代表每根木棒的长度。
输出格式:
一行一个整数,对1e9+7取模
输入输出样例
4 1 1 2 2
1
说明
对于30%的数据 N<=5000
对于100%的数据 N<=100000
by-szc
吐槽:做这道题发现了我个人的很多问题,做题实在是不够仔细!
分析:假设选4根木棍长度为a=b=c+d,我们枚举a和c,就能计算出b和d,这就变成了从所给长度中能选出多少根我们枚举长度的木棍,就要用到组合数。需要注意的是,我们要特判c是否等于d,因为选择一根c长度的木棍的方案数*选择一根d长度木棍的方案数≠选择两根c长度木棍的方案数,同时,枚举c到a/2就一定要停止,因为超过a/2,就会把一个答案算2次。关于取模的问题,其实我们只需要用到两个组合数,这两个组合数在计算的时候都不必取模,为什么呢?因为5000*4999/2 < 1e9 + 7,如果非要取模,就只有用逆元了。
如果是用数学方法做这种统计方案数的题一定要非常细心!注意所有可能但不完全相同的情况并且不能多算少算!
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> typedef long long LL; using namespace std; const int mod = 1000000007; int n; long long a[5010],maxn,ans; LL c1(LL x) { return x; } LL c2(LL x) { return x * (x - 1) / 2; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { long long t; scanf("%lld", &t); maxn = max(maxn, t); a[t]++; } for (int i = 1; i <= maxn; i++) for (int j = 1; j <= i/2; j++) { int b = i - j; if (b != j) { if (a[i] >= 2 && a[b] >= 1 && a[j] >= 1) ans += (c2(a[i])*(c1(a[j]) % mod)) % mod*(c1(a[b]) % mod) % mod; } else { if (a[i] >= 2 && a[j] >= 2) ans += c2(a[i])*c2(a[j]) % mod; } ans %= mod; } printf("%lld\n", ans % mod); return 0; }