CF1C Ancient Berland Circus

14 篇文章 0 订阅
4 篇文章 0 订阅

CF第一场比赛的最后一题居然是计算几何.
这道题的考点也是比较多,所以来写一篇题解.

  • 前置芝士

1.平面直角坐标系中两点距离公式: l = ( X 1 − X 2 ) 2 + ( Y 1 − Y 2 ) 2 l=\sqrt{(X_1-X_2)^2+(Y_1-Y_2)^2} l=(X1X2)2+(Y1Y2)2
2.海伦公式:在知道三边时用于计算三角形面积 S = p ( p − a ) ( p − b ) ( p − c ) S=\sqrt{p(p-a)(p-b)(p-c)} S=p(pa)(pb)(pc) (其中 a , b , c a,b,c a,b,c为三角形三边, p = a + b + c 2 p=\frac{a+b+c}{2} p=2a+b+c)
3.外接圆半径公式: R = a b c 4 S R=\frac{abc}{4S} R=4Sabc
4.解三角形
(知道三边求角度):
cos ⁡ B = a 2 + c 2 − b 2 2 a c \cos B=\frac{a^2+c^2-b^2}{2ac} cosB=2aca2+c2b2
cos ⁡ A = b 2 + c 2 − a 2 2 b c \cos A=\frac{b^2+c^2-a^2}{2bc} cosA=2bcb2+c2a2
cos ⁡ C = a 2 + b 2 − c 2 2 a b \cos C=\frac{a^2+b^2-c^2}{2ab} cosC=2aba2+b2c2
再将 cos ⁡ A , cos ⁡ B , cos ⁡ C \cos A,\cos B,\cos C cosA,cosB,cosC带入 arccos ⁡ ( ) \arccos() arccos()求出角度
(知道两边一夹角求第三边)
c = a 2 + b 2 − 2 a b cos ⁡ C c=\sqrt{a^2+b^2-2ab\cos C} c=a2+b22abcosC
5.欧几里得算法(gcd):看起来和这题没什么关系,具体后面会讲到.

  • 具体做法

先看一张图:
在这里插入图片描述
在图中的A,B,C为给出的点,可以发现这个正多边形与这个三角形的外接圆相同,圆心为O,AO=BO=CO,知道外接圆半径公式后可以求出AO,BO,CO,在会解三角形后可以得出 ∠ A O B \angle AOB AOB, ∠ B O C \angle BOC BOC,以及 ∠ A O C \angle AOC AOC(指图中大于 18 0 ∘ 180^\circ 180的那个角).可以发现这三个角存在一定的数量关系,及这三个角都可以表示为一个角的整数倍,及相邻黄色半径的夹角,设这个角为 ∠ α \angle\alpha α,于是图中的 ∠ A O B = 3 ∗ ∠ α \angle AOB=3*\angle\alpha AOB=3α, ∠ B O C = 2 ∗ ∠ α \angle BOC=2*\angle\alpha BOC=2α, ∠ A O C = 6 ∗ ∠ α \angle AOC=6*\angle\alpha AOC=6α,于是 ∠ α = g c d ( ∠ A O B , g c d ( ∠ B O C , ∠ A O C ) ) \angle\alpha=gcd(\angle AOB,gcd(\angle BOC,\angle AOC)) α=gcd(AOB,gcd(BOC,AOC)),角度知道后对于每个小三角形的三边都知道了,三角形个数也知道了,就可以求出总面积了.

  • 代码

#include<bits/stdc++.h>
using namespace std;
const double pi=3.1415926;
double mod(double a,double b)//小数取模
{
	return a-(int)(a/b)*b;
}
double gcd(double x,double y)//小数gcd
{
	if(y<=0.0001)return x;
	return gcd(y,mod(x,y));
}
double x,y,x2,y2,x3,y3;
int main()
{
	scanf("%lf%lf%lf%lf%lf%lf",&x,&y,&x2,&y2,&x3,&y3);
	//计算三角形三条边长
	double a=sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2));
	double b=sqrt((x-x3)*(x-x3)+(y-y3)*(y-y3));
	double c=sqrt((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3));
	double p=(a+b+c)/2;
	double r=(a*b*c)/(4*sqrt(p*(p-a)*(p-b)*(p-c)));//通过r=(abc)/(4s)得出外接圆半径
	//分别求出以三条边为低,外接圆半径为腰的三角形的顶角角度
	double angle1=acos(1-(a*a)/(2*r*r));
	double angle2=acos(1-(b*b)/(2*r*r));
	double angle3=2*pi-angle1-angle2;
	double angle=gcd(angle1,gcd(angle2,angle3))/pi*180;//题目所示的以正多边形边长为低接圆半径为腰的三角形的顶角角度
	double side=sqrt(2*r*r-2*r*r*cos(angle/180*pi));//求出正多边形的边长
	double P=(r*2+side)/2;
	double S=sqrt(P*(P-r)*(P-r)*(P-side))/*三角形面积*/*(360/angle)/*三角形个数*/;//计算面积
	printf("%.6lf",S);//保留6位小数输出
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值