UVa11401(枚举转换推公式+思维)

题意

给一正整数n,问你从1–n中选出3个不同的数能组成三角形,问你有多少种情况

分析

分析一下,这个题好像跟计算几何中的那种给你三个点的坐标,问你能组成多少个不同的三角形好像有点像。直接枚举肯定会炸,而且还有条件没有挖出来,他要求的是1–n中的数,而且还不同。那假设三条边为a,b,c,我们不妨设 a<b<c a < b < c .而且要三角形的话就要满足 a+b<c a + b < c ,除此之外还有 ba>c b − a > c .下面我们来看在最长边为c的情况下,能组成多少个三角形。枚举的话我们先要定范围,上述有两个不等式,我们稍微变形一下。 b<ca,b<c+a b < c − a , b < c + a .由于我们假设的c最大,因此有下面的不等式 ca<b<c c − a < b < c 。这里我们从1开始枚举a.
a=1 a = 1 时, c1<b<c c − 1 < b < c ,没有能取的值,ans=0
a=2 a = 2 时, c2<b<c c − 2 < b < c ,a只能取c-1,ans=1
a=3 a = 3 时, c3<b<c c − 3 < b < c ,a能取c-2,c-1,ans=2

a=c2 a = c − 2 时, 2<b<c 2 < b < c ,a能取3,4…c-1,ans=c-2
a=c1 a = c − 1 时, 1<b<c 1 < b < c ,a能取2,3…c-1,ans=c-2
由此可以推算出总和为 ans1+ans2+..+ansn=(c1)(c2)/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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值