2020ICPC上海I - Sky Garden
思维
[I-Sky Garden_第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海)(重现赛)@hzy0227 (nowcoder.com)](https://codeforces.com/gym/103202/problem/I)
题意
有 \(n\;(1<=n<=500)\) 个同心圆,半径分别为 1,2,3 ... n
有 \(m\;(1<=m<=500)\) 条过原点的直线,把一个圆分为大小相同的 2 * m 部分
圆和直线都是路径,路径长为实际的长度,两两路径会有一个交点,求所有两两交点的最短路之和
思路
\(O(1),O(n),O(n^2),O(n^3)\) 都能写,给出一个 \(O(n^2)\) 的做法
特判!!!,当 m > 1 时两个直线会在圆心有交点,而 m = 1 时圆心没有交点
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef std::pair<int, int> PII;
#define ALL(x) x.begin(),x.end()
#define pb push_back
#define fi first
#define se second
// #define double long double
const double PI = acos(-1.0);
inline ll _read() {
static ll ans;
static unsigned int c;
static bool p;
for (c = getchar(); c != '-' && (c < '0' || c > '9'); c = getchar());
if (c == '-') p = false, c = getchar(); else p = true;
for (ans = 0; c <= '9' && c >= '0'; c = getchar()) ans = ans * 10 + c - '0';
return p ? ans :-ans;
}
ll n, m;
double ans;
int main() {
cin >> n >> m;
for (ll r = 1; r <= n; r++)
{
double tmp1 = 0;
ll cnt = n - r;
//外圈除自身和直径
for (ll i = 1; i < m; i++)
{
double a = min((double)r * 2, PI * i * r / m) + 1;
tmp1 += cnt * a + (cnt - 1) * cnt / 2;
}
tmp1 *= 2;
//外圈直径
ll a = 2 * r + 1;
tmp1 += cnt * a + (cnt - 1) * cnt / 2;
//外圈自身
a = 1;
tmp1 += cnt * a + (cnt - 1) * cnt / 2;
tmp1 *= 2 * m;
//同圈除直径
double tmp2 = 0;
for (ll i = 1; i < m; i++)
tmp2 += 2 * m * min((double)r * 2, PI * i * r / m);
//同圈直径
tmp2 += m * 2 * r;
ans += tmp1 + tmp2;
}
if (m > 1)
ans += (n + 1) * n * m;
printf("%.10lf\n", ans);
return 0;
}