Sky Garden
题目大意
有n个圆他们的圆心都是(0,0),并且第i个圆的半径是i。然后有m条直线将这些圆等分成了2*m分。并且产生了一些交点。让你求任意两个不同的交点之间的最短距离之和是多少。
解题思路
看了大佬的博客看了好久才看明白,解题思路太强了。
首先我们可以知道在一个圆上的所有交点,中任意连个之间的距离肯定是
m
i
n
{
两
点
之
间
的
最
短
弧
长
,
直
径
长
度
}
min\left \{两点之间的最短弧长,直径长度\right \}
min{两点之间的最短弧长,直径长度}
然后外层圆上的点到内层圆上的点看定时要先进入内层,然后再加上对应的点到内层上点的最短距离就行了。这样层层迭代我们就可以求出答案了;思路说的可能不太清,直接看代码吧;
代码
#include<bits/stdc++.h>
using namespace std;
const int mx=5001;
const double pi=acos(-1);
double a[mx],b[mx];
int main(){
int n,m;
scanf("%d %d",&n,&m);
double cnt=0;
// 一个点到其他一半点的距离不到其对称点的那些点
for(int i=1;i<m;i++){
if(pi*i<2*m){
cnt+=pi*i/m;
}else{
cnt+=2;
}
}
// 对称位置的距离
cnt*=2;
cnt+=2;
// a[i] 表示第i个圆到其内部及其这个圆上的所有点的距离和。
// b[i] 表示第i个圆这个圆其他所有点的距离和。
a[1]=b[1]=cnt;
for(int i=2;i<=n;i++){
// 因为每层圆上的点的距离相当于半径为 1 的圆上的距离怎加了 i 倍。
b[i]=b[1]*i;
// 之所以加 (i-1)*2*m 是向内层其他点走的时候每个点都有向内走一层。
a[i]=b[i]+a[i-1]+(i-1)*2*m;
}
double ans=0;
for(int i=1;i<=n;i++){
// 2*m*(a[i]-b[i]) 表示这层圆上的所有点到内部其他点的距离和
// m*b[i] 表示的是这层圆上的所有两两不同点的距离和
ans+=2*m*(a[i]-b[i])+m*b[i];
//如果m大于1说明中间有交点,
//要求出每个圆上的点到焦点的距离和。
if(m>1){
ans+=2*i*m;
}
}
printf("%.10lf\n",ans);
return 0;
}