zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    基础很重要~~04.表表达式-上篇
    【T-SQL基础】03.子查询
    【T-SQL基础】02.联接查询
    【T-SQL基础】01.单表查询-几道sql查询题
    【.Net底层剖析】3.用IL来理解属性
    SQL-基础知识
    IL指令速查
    黑客成长之路-01.新手篇-设置路由器
    《拆掉思维里的墙》~~想跳槽的同学可以先看看这本书!
    【解决方案】安装vssdk_full.exe遇到的问题
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/10799543.html
Copyright © 2011-2022 走看看