写了一种不太快但是比较好理解的代码:
大致就是二分(这里二分应该是可以O(1)的)
先让整个2n边形的某个顶点对着(1,0),在这种情况下以(0,0)为中心构造的正方形显然不是最小的。我们也可以发现只需要绕着原点转一个角度就能够造出最小的正方形:可以画一画发现,旋转的角度为 π 4 n \frac{\pi}{4n} 4nπ
然后对于C1的代码,只要把二分函数里的now角度改一下就好了
const int N=200010,M=N*2,mod=1e9+7;
int n,m,k,a[N];
string p;
double angle;
bool check(double w){
w/=2.0;
double tmp=(PI-angle)/2.0;
double r=sin(tmp)/sin(angle);
// debug(r);
double now=PI/(4.0*n);
bool ok=true;
for(int i=0;i<n*2;++i){
double x=r*cos(now),y=r*sin(now);
if(sign(x-w)>0||sign(x+w)<0||sign(y-w)>0||sign(y+w)<0) {
ok=false;
break;
}
now += angle;
}
if(ok) return ok;
now=0;ok=true;
for(int i=0;i<n*2;++i){
double x=r*cos(now),y=r*sin(now);
if(sign(x-w)>0||sign(x+w)<0||sign(y-w)>0||sign(y+w)<0) {
return false;
}
now += angle;
}
return true;
}
void solve(){
double one=PI/180.0;
scanf("%d",&n);
angle=PI/n;
double l=1,r=1e18;
int cnt=200;
while(cnt--){
double mid=(l+r)/2.0;
if(check(mid)) r=mid;
else l=mid;
}
printf("%.10lf\n",l);
}