可以不失一般性地假设底边$AB=1$,且$\angle DAC$是八个角中最小的。
从左往右枚举底部四个角$\angle DAC$, $\angle CAB$, $\angle ABD$, $\angle DBC$的值,将其依次记作$a,b,c,d$。
从右往左把顶部四个角$\angle BCA$, $\angle DCA$, $\angle BDC$, $\angle ADB$依次标记为$e,f,g,h$。
若$a,b,c,d$都是整数,那么显然$e=180^{\circ}-b-c-d$和$h=180^{\circ}-a-b-c$也都是整数,因此只需计算并找出f和g也都是整数的情况即可。
用正弦定理和余弦定理(以及$|AB|=1$)易得
\begin{align*}
|AD|&=\frac{\sin(c)}{\sin(a+b+c)} \\
|AC|&=\frac{\sin(c+d)}{\sin(b+c+d)} \\
|CD|&=\sqrt{|AD|^2+|AC|^2-2|AD|\cdot|AC|\cos a} \\
|BC|&=\frac{\sin b}{\sin(b+c+d)} \\
|BD|&=\frac{\sin(a+b)}{\sin(a+b+c)} \\
\cos f&=\frac{|CD|^2+|AC|^2-|AD|^2}{(2|CD|\cdot|AC|} \\
\cos g&=\frac{|CD|^2+|BD|^2-|BC|^2}{2|CD|\cdot|BD|}
\end{align*}
注意f和g需要用反余弦计算,若用反正弦将无法区分锐角和钝角。
枚举时还应注意a是八个角中最小的,且所有八个角的和为$360^{\circ}$。
旋转和翻转最多能生成八组角度的排列(旋转四种乘以翻转两种),我们把这八种情况底部四个角从左到右形成的四元组排序,取其中最小的一组作为键值来去重。
结果是$129325$。
注: 本题在实现上有很多容易出错的细节,我花了两三天时间才完全调试正确。主要的难点有:1)需要合理选择变量,使之既能压缩枚举量,又不遗漏不重复,同时又便于判定整数角。2) 答案严格依赖于题面中所给出的精度范围。
import math
epsilon=10**(-9)
sin=[math.sin(math.radians(i)) for i in range(181)]
cos=[math.cos(math.radians(i)) for i in range(181)]
r=set()
for a in range(1,46):
for b in range(a,181-3*a):
for c in range(a,181-2*a-b):
for d in range (a,181-a-b-c):
AD=1.0*sin[c]/sin[a+b+c]
AC=1.0*sin[c+d]/sin[b+c+d]
CD=math.sqrt(AD*AD+AC*AC-2*AD*AC*cos[a])
BC=1.0*sin[b]/sin[b+c+d]
BD=1.0*sin[a+b]/sin[a+b+c]
x,y=math.degrees(math.acos((CD*CD+AC*AC-AD*AD)/(2*CD*AC))),math.degrees(math.acos((CD*CD+BD*BD-BC*BC)/(2*CD*BD)))
DCA,BDC=int(round(x)),int(round(y))
#if a==1 and b==2 and c==90 and d==1: print x,y,DCA,BDC,abs(x-DCA)<=epsilon,abs(y-BDC)<=epsilon,DCA>=a,BDC>=a,180-b-c-d>=a,180-a-b-c>=a
if abs(x-DCA)<=epsilon and abs(y-BDC)<=epsilon and DCA>=a and BDC>=a:
e,f,g,h=180-b-c-d,DCA,BDC,180-a-b-c
if a+b+c+d+e+f+g+h==360 and min(a,b,c,d,e,f,g,h)==a:
r.add(min((a,b,c,d),(c,d,e,f),(e,f,g,h),(g,h,a,b),(d,c,b,a),(f,e,d,c),(h,g,f,e),(b,a,h,g)))
print len(r)
|