题意
给一正整数n,问你从1–n中选出3个不同的数能组成三角形,问你有多少种情况
分析
分析一下,这个题好像跟计算几何中的那种给你三个点的坐标,问你能组成多少个不同的三角形好像有点像。直接枚举肯定会炸,而且还有条件没有挖出来,他要求的是1–n中的数,而且还不同。那假设三条边为a,b,c,我们不妨设
a<b<c
a
<
b
<
c
.而且要三角形的话就要满足
a+b<c
a
+
b
<
c
,除此之外还有
b−a>c
b
−
a
>
c
.下面我们来看在最长边为c的情况下,能组成多少个三角形。枚举的话我们先要定范围,上述有两个不等式,我们稍微变形一下。
b<c−a,b<c+a
b
<
c
−
a
,
b
<
c
+
a
.由于我们假设的c最大,因此有下面的不等式
c−a<b<c
c
−
a
<
b
<
c
。这里我们从1开始枚举a.
a=1
a
=
1
时,
c−1<b<c
c
−
1
<
b
<
c
,没有能取的值,ans=0
a=2
a
=
2
时,
c−2<b<c
c
−
2
<
b
<
c
,a只能取c-1,ans=1
a=3
a
=
3
时,
c−3<b<c
c
−
3
<
b
<
c
,a能取c-2,c-1,ans=2
…
a=c−2
a
=
c
−
2
时,
2<b<c
2
<
b
<
c
,a能取3,4…c-1,ans=c-2
a=c−1
a
=
c
−
1
时,
1<b<c
1
<
b
<
c
,a能取2,3…c-1,ans=c-2
由此可以推算出总和为
ans1+ans2+..+ansn=(c−1)∗(c−2)/2
a
n
s
1
+
a
n
s
2
+
.
.
+
a
n
s
n
=
(
c
−
1
)
∗
(
c
−
2
)
/
2
,但是这里有重复的,a=3的时候b可以取c-2,但是当a=c-2时,b也取了3.同理其他。每一个情况好像都算了两次,不过
a==b
a
==
b
的这种情况只会算一次(为什么请往下看),但是题目是不让重复取值的,所以们要先减去相同的,再除以二。
下面我们再找有多少个相同的。还是看上面的枚举,找规律发现对于枚举的每个a,b的取值数量都是a-1,当而且是从c-1开始往前面取,所以对于每次枚举,如果a大于b能取到的最小值,则以后的情况必然都有
a==b
a
==
b
,而且仅有一次。临界情况就是a=c-1-a,得到a=(c-1)/2时正好有这种情况,至于为什么是下整,可以模拟几组数据看看。
有了上述结论和公式,我们得到了一个结论,设f(x)为最长边为x,且三条边不重复的三角形的数量。可以在O(1)的时间内求出f(x),已经推出了公式。那么题目要求的就等价于求f(1)+f(2)+…+f(n),这个可以递推求,时间复杂度O(n),具体看代码
顺便一提,这种枚举推公式的思想很重要,上次华师校赛已经有过这个题了,还想了半天。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
const ll MAXN = 1e6 + 5;
ll f[MAXN];
int main()
{
ios::sync_with_stdio(false);
ll n;
for (ll i = 4; i <= MAXN; i++)
f[i] = f[i-1] + ((i - 1)*(i - 2) / 2 - (i - 1) / 2) / 2;
while (cin >> n)
{
if (n < 3) break;
cout << f[n] << endl;
}
return 0;
}