欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

19_05_01校内训练[polygon]

发布时间:2023/12/18 编程问答 54 豆豆
生活随笔 收集整理的这篇文章主要介绍了 19_05_01校内训练[polygon] 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

题意

把一个边长为1的正n边形放到一个正m边形中,要求m边形完全覆盖n边形,可以有交点,并且中心重合。求正m边形的最小边长,至少精确到6位。要求logn计算。


 

思考

先考虑m|n的情况。

我们知道,正m边形的边长与可行区域(即可以完全覆盖的那些角度)形成单射,当且仅当所有可行区域都成为可数的点时,答案最优。(可以理解为再缩小一点就无解了)

这样不难证明,把正n边形的几条边刚好卡在正m边形上是最优的。如n=8,m=4:

这时正m边形的边长是容易计算的。相信大家都会初中数学。

这样再考虑一般情况。由于是中心重合,正n边形旋转2π/m度后仍然是能被覆盖的。

在所有可行的旋转过程中,将最外圈的点连起来,仍然形成一个正多边形,且边数为lcm(n,m)。

例如,n=4,m=6:

用紫线围出来的正12边形即为正方形得到的结果。

至于正确性,在于所有的可行区域都是单点。

这样一来,就可以直接转化为上一个问题。公式认真推即可。


 

代码

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long int ll; 4 const double pi=acos(-1); 5 ll n,m; 6 ll gcd(ll x,ll y) 7 { 8 return x%y==0?y:gcd(y,x%y); 9 } 10 ll lcm(ll x,ll y) 11 { 12 return x/gcd(x,y)*y; 13 } 14 double solve(ll n,ll m) 15 { 16 double len=1/(2*tan(pi/n)); 17 double th=(n/m)*pi/n; 18 return tan(th)*len*2; 19 } 20 int main() 21 { 22 ios::sync_with_stdio(false); 23 cin>>n>>m; 24 double len=1/(2*sin(pi/n)); 25 n=lcm(n,m); 26 double a=sin(pi/n)*len*2; 27 cout<<fixed<<setprecision(9)<<solve(n,m)*a<<endl; 28 return 0; 29 } View Code

 

转载于:https://www.cnblogs.com/GreenDuck/p/10799543.html

总结

以上是生活随笔为你收集整理的19_05_01校内训练[polygon]的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。