三角形——推公式推到手抽筋的等边三角形

本文详细介绍了在特殊坐标系下,通过分类讨论的方法,推导出计算三角形面积的公式,包括三点共线、两点在同一条边上以及三点在不同边上的情况,最终得出一种高效计算三角形面积的方法。

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

三角形

解析

不难想到,三角形三个顶点的排列情况应该有以下三种:

1.三点共线,显然无法组成三角形;

2.两点在同一条边上:
三角形2
3.三点都在不同的边上:
三角形3
蓝色部分为我们选出来的三角形,绿色部分是剩余的三角形。

  • 解法1

容易想出来的一种暴力的方法是,针对第一种三角形和第二种三角形分别处理。为了方便,我们先建立一个特殊的坐标系:
三角形4

对于两点共边的三角形,枚举三个点的位置 i , j , k i,j,k i,j,k i i i j j j在同一坐标轴上,为了防止重复,设 i i i随时在 j j j的后面,根据面积的定义,可以得到以下几行代码:

for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j)
for(int k=1;k<=n;++k)
ans+=(j-i+1)*k;

于是面积就被很简单的暴力 O ( n 3 ) O(n^3) O(n3)地算出来啦!

对于第二种情况,直接算选出的三角形的面积不好算,但是我们没选出来的部分构成了三个三角形,且比较好计算。所以我们可以通过计算周围三个三角形的方式,运用补集转化的思想,用整个三角形的面积减去周围小三角形的面积,求出中间的三角形的面积,设大三角形的面积为 S S S,这里应注意一条边被我们分成了 ( n + 1 ) (n+1) (n+1)分,所以 S = ( n + 1 ) 2 S=(n+1)^2 S=(n+1)2

那么计算就很简单了,周围三个小三角形的面积分别是 i × j i\times j i×j i × k i\times k i×k j × k j\times k j×k,代码如下,复杂度为 O ( n 3 ) O(n^3) O(n3)

for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
for(int k=1;k<=n;++k)
ans+=S-i*j-i*k-j*k;
  • 解法2

显然,上面 O ( n 3 ) O(n^3) O(n3)的方法最多只能过 30 % 30 \% 30%的数据,而最大数据是 1 0 9 10^9 109,会 T L E TLE TLE得很惨。

略微思考一下,既然是 1 0 9 10^9 109,那么多半是要推公式了。

再思考一下,答案就是两个式子的和:

对于第一种情况,将 i i i轴看做底边,答案即是底为1的三角形的面积和+底为2的三角形面积和+···底为n的三角形面积和。动动手指头,底为1的三角形有 n − 1 n-1 n1个,底为2的三角形有 n − 2 n-2 n2个,···底为 n n n的三角形有 1 1 1个,即 n − ( n − 1 ) n-(n-1) n(n1)个,而每个三角形的高(设为 k k k)可以为 1 1 1~ n n n的任意一个数,所以推出公式为:
∑ k = 1 n ( n − 1 ) × 1 × k + ( n − 2 ) × 2 × k + ⋯ + ( n − ( n − 1 ) ) × n × k \sum^n_{k=1}(n-1)\times1\times k+(n-2)\times2\times k+\cdots+(n-(n-1))\times n\times k k=1n(n1)×1×k+(n2)×2×k++(n(n1))×n×k
k k k提出来,得到:
∑ k = 1 n k × [ ( n − 1 ) × 1 + ( n − 2 ) × 2 + ⋯ + ( n − ( n − 1 ) ) × n ] \sum^n_{k=1}k\times[(n-1)\times1+(n-2)\times2+\cdots+(n-(n-1))\times n] k=1nk×[(n1)×1+(n2)×2++(n(n1))×n]
A = ∑ k = 1 n A=\sum_{k=1}^n A=k=1n,即 A = n ( n + 1 ) 2 A=\frac{n(n+1)}{2} A=2n(n+1),公式化简为:
A × [ ( n − 1 ) × 1 + ( n − 2 ) × 2 + ⋯ + ( n − ( n − 1 ) ) × n ] A\times[(n-1)\times1+(n-2)\times2+\cdots+(n-(n-1))\times n] A×[(n1)×1+(n2)×2++(n(n1))×n]

A A A是已知的,现在讨论如何求:
( n − 1 ) × 1 + ( n − 2 ) × 2 + ⋯ + ( n − ( n − 1 ) ) × n (n-1)\times1+(n-2)\times2+\cdots+(n-(n-1))\times n (n1)×1+(n2)×2++(n(n1))×n
很明显,将 ( n − 1 ) 、 ( n − 2 ) (n-1)、(n-2) (n1)(n2)括号内的 1 , 2 , ⋯   , n − 1 1,2,\cdots,n-1 1,2,,n1提出来,用乘法分配律,得到:
n × 1 + n × 2 + ⋯ n × n − ( 1 2 + 2 2 + ⋯ + n 2 ) n\times1+n\times2+\cdots n\times n-(1^2+2^2+\cdots+n^2) n×1+n×2+n×n(12+22++n2)
用公式分别表示两边的式子,得到:
n × A − n ( n + 1 ) ( 2 n + 1 ) 6 n\times A-\frac{n(n+1)(2n+1)}{6} n×A6n(n+1)(2n+1)
代入原式子,得到:
n × A 2 − n ( n + 1 ) ( 2 n + 1 ) 6 × A n\times A^2-\frac{n(n+1)(2n+1)}{6}\times A n×A26n(n+1)(2n+1)×A
代入 A A A,化简,得到式子:
n 5 + n 4 − n 3 − n 2 12 \frac{n^5+n^4-n^3-n^2}{12} 12n5+n4n3n2
因为我们只讨论了 i i i轴上的情况,一共有三个坐标轴,且每种情况的高可以在左边,也可以在右边,并且这些情况都不会重复(不懂得请自己简单证明),如图:
三角形5
其中黑色边和红色边的三角形的面积相等,所以答案还要乘以6,即:
n 5 + n 4 − n 3 − n 2 2 \frac{n^5+n^4-n^3-n^2}{2} 2n5+n4n3n2

对于第二种情况,从刚才暴力的代码中我们可以明显地看出来我们要求的公式:
∑ i = 1 n ∑ j = 1 n ∑ k = 1 n S − i j − j k − i k \sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^nS-ij-jk-ik i=1nj=1nk=1nSijjkik
其中 S = ( n + 1 ) 2 S=(n+1)^2 S=(n+1)2,提出 S S S,得到:
n 3 × S − ∑ i = 1 n ∑ j = 1 n ∑ k = 1 n i j + j k + i k n^3\times S-\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^nij+jk+ik n3×Si=1nj=1nk=1nij+jk+ik
其中 n 3 × S n^3\times S n3×S很好求出来所以我们要求的只是:
∑ i = 1 n ∑ j = 1 n ∑ k = 1 n i j + j k + i k \sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^nij+jk+ik i=1nj=1nk=1nij+jk+ik
可以看出,这个式子的结果明显是与 n n n有关的定值,为了简化公式,我们先假设 i , j i,j i,j不变,只考虑 k k k,即求:
∑ k = 1 n i j + j k + i k \sum_{k=1}^nij+jk+ik k=1nij+jk+ik
其中 i , j i,j i,j与式子无关,可以提出来,在因式分解,化简得:
n i j + ∑ k = 1 n k × ( i + j ) nij+\sum_{k=1}^nk\times(i+j) nij+k=1nk×(i+j)
再化简,得:
n i j + ( i + j ) × ∑ k = 1 n k nij+(i+j)\times \sum_{k=1}^nk nij+(i+j)×k=1nk

n i j + ( i + j ) × A nij+(i+j)\times A nij+(i+j)×A
好了,现在我们抵消掉 k k k的影响了,暴力枚举 i i i j j j,我们可以发现,我们要求的是以下式子的和:
三角形6
现在考虑 i = 1 i=1 i=1的情况:

我们分别求 1 × 1 × n + 1 × 2 × n + ⋯ 1 × n × n 1\times 1\times n+1\times 2\times n+\cdots1\times n\times n 1×1×n+1×2×n+1×n×n ( 1 + 1 ) × A + ( 1 + 2 ) × A + ⋯ + ( 1 + n ) × A (1+1)\times A+(1+2)\times A+\cdots+(1+n)\times A (1+1)×A+(1+2)×A++(1+n)×A

对于 1 × 1 × n + 1 × 2 × n + ⋯ 1 × n × n 1\times 1\times n+1\times 2\times n+\cdots1\times n\times n 1×1×n+1×2×n+1×n×n
1 × n 1\times n 1×n提取出来,就变成了 1 × n × A 1\times n\times A 1×n×A
对于 ( 1 + 1 ) × A + ( 1 + 2 ) × A + ⋯ + ( 1 + n ) × A (1+1)\times A+(1+2)\times A+\cdots+(1+n)\times A (1+1)×A+(1+2)×A++(1+n)×A
拆开括号,变成 1 × n × A + A 2 1\times n\times A+A^2 1×n×A+A2
加起来就是 1 × n × A + 1 × n × A + A 2 1\times n\times A+1\times n\times A+A^2 1×n×A+1×n×A+A2
合并一下就是 2 × 1 × n × A + A 2 2\times 1 \times n\times A+A^2 2×1×n×A+A2

所以我们可以将原式子的和转化为:
∑ i = 1 n ( 2 × i × n × A + A 2 ) \sum_{i=1}^n(2\times i\times n\times A+A^2) i=1n(2×i×n×A+A2)
化简一下,就变成了
3 n A 2 3nA^2 3nA2
A A A代入原式子,得到
n 5 + 2 n 4 + n 3 4 \frac{n^5+2n^4+n^3}{4} 4n5+2n4+n3

将两种情况的式子加起来,就得到了最终的表达式
3 n 5 + 4 n 4 − n 3 − 2 n 2 4 \frac{3n^5+4n^4-n^3-2n^2}{4} 43n5+4n4n32n2
预处理出4的逆元,再用快速幂就求出了最终我们需要的答案,复杂度近似 O ( 1 ) O(1) O(1),是不是很简单呢?

代码

#include<cstdio>
#define ll long long
#define mod 1000000007
using namespace std;

ll n,ans;
ll inv=250000002;//4的逆元

ll quick(ll x,ll y)
{
	ll ret=1;
	while(y)
	{
		if(y&1)ret=(ll)(ret*x)%mod;
		x=(ll)(x*x)%mod;
		y>>=1;
	}
	return ret;
}

int main()
{
	scanf("%lld",&n);
	ans=((ll)(3*quick(n,5))%mod+(ll)(4*quick(n,4))%mod-quick(n,3)-(ll)2*quick(n,2))%mod;
	ans=(ll)(ans*inv)%mod;
	ans=(ans%mod+mod)%mod;
	printf("%lld",ans);
	return 0;
}

总结

这道题就是疯狂地推公式,但是从一些细节中我们可以总结出以下几点:
1.根据题目特性,判断是否分类讨论;
2.对于一些数据范围比较大的题目,想到正解的复杂度应是 O ( log ⁡ n ) O(\log n) O(logn) O ( n ) O(\sqrt n) O(n )或推出公式 O ( 1 ) O(1) O(1)的;
3.在面对变量较多但是有一定共性的公式时,可以采用主元法,即只把一个看作一个变量,其余的看作常量,化繁为简,由大到小;
4.这些题的公式比较复杂,所以我们运算的正确率一定要高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值