Prof. Du and Prof. Pang plan to build a sky garden near the city of Allin. In the garden, there will be a plant maze consisting of straight and circular roads.
On the blueprint of the plant maze, Prof. Du draws nn circles indicating the circular roads. All of them have center (0, 0)(0,0). The radius of the ii-th circle is ii.
Meanwhile, Prof. Pang draws mm lines on the blueprint indicating the straight roads. All of the lines pass through (0, 0)(0,0). Each circle is divided into 2m2m parts with equal lengths by these lines.
Let QQ be the set of the n+mn+m roads. Let PP be the set of all intersections of two different roads in QQ. Note that each circular road and each straight road have two intersections.
For two different points a\in Pa∈P and b\in Pb∈P, we define dis(\{a, b\})dis({a,b}) to be the shortest distance one needs to walk from aa to bb along the roads. Please calculate the sum of dis(\{a, b\})dis({a,b}) for all \{a, b\}\subseteq P{a,b}⊆P.
Input
The only line contains two integers n,m~(1\le n,m\le 500)n,m (1≤n,m≤500).
Output
Output one number – the sum of the distances between every pair of points in PP.
Your answer is considered correct if its absolute or relative error does not exceed 10^{-6}10−6.
Examples
Input
1 2
Output
14.2831853072
Input
2 3
Output
175.4159265359
Note
dis(p_1, p_2)=dis(p_2, p_3)=dis(p_3, p_4)=dis(p_1, p_4)=\frac{\pi}{2}dis(p1,p2)=dis(p2,p3)=dis(p3,p4)=dis(p1,p4)=2π
dis(p_1, p_5)=dis(p_2, p_5)=dis(p_3, p_5)=dis(p_4, p_5)=1dis(p1,p5)=dis(p2,p5)=dis(p3,p5)=dis(p4,p5)=1
dis(p_1, p_3)=dis(p_2, p_4)=2dis(p1,p3)=dis(p2,p4)=2
题意: 给出n个同心圆,第i个圆的半径为i,又给出m条直线,每条直线都过圆心且将圆均匀分割,求这张图上所有交点两两之间最短距离的和。
分析: 可以把答案分成三部分,一部分是每层圆上交点两两之间距离和,一部分是各点到圆心距离和,一部分是内层圆到所有外层圆交点两两距离和,验证的话可以由内层到外层依次枚举圆上各点,显然可知答案一定由这三部分组成。
现在考虑求第一部分答案,每层圆上交点两两距离和。由于圆上各点分布具有对称性,可以枚举其中一个点到圆上其余各点的距离和,结果*圆上点数/2就是答案。在枚举点到点的最短距离时实际上有三条路径,一条走圆弧,一条走两线段,一条走一段圆弧两小段线段,列出公式分析一下发现要么走圆弧,要么走两线段,在不同角度下这两条路总有一条比第三条路要优,所以直接取一个min作为两点间最短距离就可以了。由于在计算的过程中每次加的都是某个数*R,所以每层的最终结果是关于R的一次函数,那么对于每层的结果我们都可以代R求得,最后ans1就是把每层上的结果加和。
之后是第二部分答案,这时候要注意如果只有一条直线的情况圆心处是不会交出交点的,也就是不存在这部分答案。对于两条及以上的直线,这部分的答案就是cnt+2*cnt+......+(n-1)*cnt+n*cnt,cnt为圆上交点的个数,画出图来很容易看出这个公式。所以这部分答案就是等差数列求和,ans2 = cnt*(1+n)*n/2。
最后一部分也是比较难想的一部分,要考虑内层圆上的点到外层所有点的距离和。首先要知道内层圆的点到外层圆上点的最短路径是什么,脑内枚举一下所有路径发现最短路径一定是先从内层圆转到与外层点相同角度的位置,然后走直线到达。之后我们可以画图观察一下看有没有什么规律:
枚举内层圆上点1、2、3、4到达外层圆上点5、6、7、8的最短距离之和。先从点1开始,绿色路径+黄色路径即为到各点的最短路径。
之后枚举点2。
枚举点3。
最后枚举点4。
观察最后一张图可以发现确实是有规律的,设cnt为圆上点数,R1为大圆半径,R2为小圆半径,每个点都会贡献cnt*(R1-R2)的距离,即上图黄线,一共有cnt个点,所以贡献cnt*cnt*(R1-R2)。再看绿线部分,这不就是一层圆上各点距离吗,这个距离之前是求过的,这里拿来用就行了。最后ans3就是这两部分相加,当然上面计算的只是到某一个外层圆的距离和,要对所有外层圆距离和求和,方法还是一样的。
最后总答案就是ans1+ans2+ans3。
具体代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const double pi = acos(-1.0);
//注意一条直线时圆心不是有效交点!
signed main()
{
int n, m;
cin >> n >> m;
int cnt = 2*m;//每个圆上点数
double sum = 0, ans1 = 0, ans2 = 0, ans3 = 0;
double theta = 2*pi/cnt;
for(int i = 1; i < cnt; i++)
sum += min(2.0, min(theta*i, 2*pi-theta*i));//走两直线还是走圆弧
sum = sum*cnt/2;//第一层圆上任取两交点距离和
//每层圆上各点距离和(同一层圆上)
for(int i = 1; i <= n; i++)
ans1 += sum*i;
//如果至少存在两条直线,圆心也是交点
if(m != 1)
ans2 = cnt*(1+n)*n/2;
//各层之间各点间距离和(不同层圆上)
for(int i = 1; i <= n; i++)
for(int j = i+1; j <= n; j++)
ans3 += sum*i*2+cnt*cnt*(j-i);
double ans = ans1 + ans2 + ans3;
printf("%.8f\n", ans);
return 0;
}