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

本文探讨了一种高效算法,用于计算在给定范围内能够组成三角形的不同整数组合的数量。通过枚举和数学推导,文章提出了一种在O(1)时间内计算特定条件下三角形组合数量的方法,并通过递推求和实现了O(n)时间复杂度的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

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

分析

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

a=c2a=c−2时,2<b<c2<b<c ,a能取3,4…c-1,ans=c-2
a=c1a=c−1时,1<b<c1<b<c ,a能取2,3…c-1,ans=c-2
由此可以推算出总和为ans1+ans2+..+ansn=(c1)(c2)/2ans1+ans2+..+ansn=(c−1)∗(c−2)/2,但是这里有重复的,a=3的时候b可以取c-2,但是当a=c-2时,b也取了3.同理其他。每一个情况好像都算了两次,不过a==ba==b的这种情况只会算一次(为什么请往下看),但是题目是不让重复取值的,所以们要先减去相同的,再除以二。
下面我们再找有多少个相同的。还是看上面的枚举,找规律发现对于枚举的每个a,b的取值数量都是a-1,当而且是从c-1开始往前面取,所以对于每次枚举,如果a大于b能取到的最小值,则以后的情况必然都有a==ba==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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值