description
今天助教在做一道美术题:
现在有 个圆,均以坐标原点为圆心,半径分别为 ,然后还有 条过圆心的直线,直线怎么画才能让看图的人视觉效果最好?
助教很快的回答说:
那当然是直接等分圆好呀。就是 条线会和每个圆产生 个交点,让相邻两个点之间的距离相等呀。
于是就有了这样的图片:
老师看到这个图片以后觉得很美,想知道一个问题:
这些圆和线有很多交点,这些交点两两之间的最短路之和是多少?
输入格式
输入共一行,包括两个整数 ,分别表示同心圆的个数和直线的条数。
输出格式
输出一个浮点数,表示这些圆和线的交点两两之间的最短路之和。如果你的答案是 ,标准答案是 ,当且仅当 时,你将通过此题。
样例说明
总距离为 。
题目不知道为什么显示不完整了,贴个图吧
code
直接看代码吧,更重要的是这个公式
#include <cstdio>
#include <iostream>
using namespace std;
const double pi = 3.141592653589793238;
int main()
{
double n, m, i, j;
double hu; //弧长
cin >> n >> m;
double result = 0;
/*
下标从1开始,第i个圆的半径为i,l[i]保存的是第i个圆上的任意一点
到其他各点,不包括圆心的距离之和,
lsum[i]保存的是第i个圆上所有点到其他各点(不包括圆心)的距离之和
*/
double l[(int)(n + 1)];
double lsum[(int)(n + 1)];
for(i = 1; i <= n; i++) {
int i0 = (int)i;
lsum[i0] = 0;
for(j = 1; j < m; j++) {
hu = j * pi * i / m;
if(hu >= 2 * i)
lsum[i0] += 2 * i;
else
lsum[i0] += hu;
}
l[i0] = 2 * lsum[i0] + 2 * i;
lsum[i0] = m * l[i0];
}
if(m != 1)
result += lsum[1] + 2 * m;
else
result += lsum[1];
if(n == 1) {
printf("%.10lf\n", result);
return 0;
}
for(i = 2; i <= n; i++) {
if(m != 1)
result += lsum[(int)i] + 2 * m * i + 2 * m * m * i * (i - 1);
else
result += lsum[(int)i] + 2 * m * m * i * (i - 1);
for(j = i - 1; j >= 1; j--)
result += 2 * m * l[(int)j];
}
printf("%.10lf\n", result);
return 0;
}