Problem:
問題 F
ボ〜ル
問題文
2 次元平面上の原点にボールがあり，
x
軸の正方向との角度が反時計回りに見て
0
度
180
度までの間の方向に一様な確率で発射されようとしている (発射される方向は整数角であるとは限らない)．ボールの大きさは十分小さく，平面上では点であると見なすことにする．この問題における目的は，このボールをできるだけ高い確率で捕獲することである．
平面上に
N
個の場所
(x
i
, y
i
)
が与えられる．ボールを捕獲するために，あなたは
N
個の場所から
K
個の場所を選んで，それぞれの場所に人を配置することができる．人は
i
番目の与えられた場所に対して半径
r
i
以内の距離まで動いてボールを取ることが出来る．
人の配置をうまく選んでボールを捕獲できる確率を最大にするとき，その確率を出力せよ．
入力形式
入力は以下の形式で与えられる．
N
K
x
1
y
1
r
1
...
x
N
y
N
r
N
N
はボールを捕獲するために人を置くための場所の数であり，
K
はその中から使うことの出来る場所の数である．
(x
i
, y
i
)
は
i
番目の場所の座標であり，
r
i
はそこから動くことの出来る距離である．
出力形式
確率を小数表記で
1
行に出力せよ．小数点以下何桁でも出力して構わないが，相対誤差あるいは絶対誤差が
10
-6
未満になっていなければならない．
制約
1≤ N≤ 1,500, 1≤ K≤ N
|x
i
| ≤ 1,000, |y
i
| ≤ 1,000, 1 ≤ r
i
< (x
i
2
+ y
i
2
)
1/2
入力値はすべて整数である．
入出力例
入力例 1
2 1
10 10 10
-10 10 10
出力例 1
0.50
2
つ場所があり，そのうちのどちらかに人を配置できる．この場合，どちらに配置しても確率は
1/2
になる．
入力例 2
2 2
10 10 10
-10 10 10
出力例 2
1.0
入力例 3
5 3
-10 -10 5
10 10 2
-10 10 3
-10 0 4
10 0 2
出力例 3
0.3574057314330
入力例 4
4 2
1 1 1
2 2 2
3 3 3
4 4 4
出力例 4
0.50

Submitted solutions:

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007;
// const int MOD = 998244353;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
const int dy8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx8[] = {0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} iosetup;

namespace Geometry {
  using Real = double;

  int sgn(Real x) { return x > EPS ? 1 : x < -EPS ? -1 : 0; }

  Real degree_to_radian(Real d) { return d * M_PI / 180; }
  Real radian_to_degree(Real r) { return r * 180 / M_PI; }

  struct Point {
    Real x, y;
    Point(Real x = 0, Real y = 0) : x(x), y(y) {}
    Real abs() const { return sqrt(norm()); }
    Real arg() const { Real res = atan2(y, x); return res < 0 ? res + M_PI * 2 : res; }
    Real norm() const { return x * x + y * y; }
    Point rotate(Real angle) const { Real cs = cos(angle), sn = sin(angle); return Point(x * cs - y * sn, x * sn + y * cs); }
    Point unit_vector() const { Real a = abs(); return Point(x / a, y / a); }
    pair<Point, Point> normal_unit_vector() const { Point p = unit_vector(); return {Point(-p.y, p.x), Point(p.y, -p.x)}; }
    Point &operator+=(const Point &p) { x += p.x; y += p.y; return *this; }
    Point &operator-=(const Point &p) { x -= p.x; y -= p.y; return *this; }
    Point &operator*=(Real k) { x *= k; y *= k; return *this; }
    Point &operator/=(Real k) { x /= k; y /= k; return *this; }
    bool operator<(const Point &p) const { int x_sgn = sgn(p.x - x); return x_sgn != 0 ? x_sgn == 1 : sgn(p.y - y) == 1; }
    bool operator<=(const Point &p) const { return !(p < *this); }
    bool operator>(const Point &p) const { return p < *this; }
    bool operator>=(const Point &p) const { return !(*this < p); }
    Point operator+() const { return *this; }
    Point operator-() const { return Point(-x, -y); }
    Point operator+(const Point &p) const { return Point(*this) += p; }
    Point operator-(const Point &p) const { return Point(*this) -= p; }
    Point operator*(Real k) const { return Point(*this) *= k; }
    Point operator/(Real k) const { return Point(*this) /= k; }
    friend ostream &operator<<(ostream &os, const Point &p) { return os << '(' << p.x << ", " << p.y << ')'; }
    friend istream &operator>>(istream &is, Point &p) { Real x, y; is >> x >> y; p = Point(x, y); return is; }
  };

  struct Segment {
    Point s, t;
    Segment(const Point &s = {0, 0}, const Point &t = {0, 0}) : s(s), t(t) {}
  };
  struct Line : Segment {
    using Segment::Segment;
    Line(Real a, Real b, Real c) {
      if (sgn(a) == 0) {
        s = Point(0, -c / b); t = Point(1, s.y);
      } else if (sgn(b) == 0) {
        s = Point(-c / a, 0); t = Point(s.x, 1);
      } else if (sgn(c) == 0) {
        s = Point(0, 0); t = Point(1, -a / b);
      } else {
        s = Point(0, -c / b); t = Point(-c / a, 0);
      }
    }
  };

  struct Circle {
    Point p; Real r;
    Circle(const Point &p = {0, 0}, Real r = 0) : p(p), r(r) {}
  };

  Real cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }
  Real dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }

  int ccw(const Point &a, const Point &b, const Point &c) {
    Point ab = b - a, ac = c - a;
    int sign = sgn(cross(ab, ac));
    if (sign == 0) {
      if (sgn(dot(ab, ac)) == -1) return 2;
      if (sgn(ac.norm() - ab.norm()) == 1) return -2;
    }
    return sign;
  }

  Real get_angle(const Point &a, const Point &b, const Point &c) {
    Real ba_arg = (a - b).arg(), bc_arg = (c - b).arg();
    if (ba_arg > bc_arg) swap(ba_arg, bc_arg);
    return min(bc_arg - ba_arg, M_PI * 2 - (bc_arg - ba_arg));
  }

  Real closest_pair(vector<Point> ps) {
    int n = ps.size();
    assert(n > 1);
    sort(ALL(ps));
    function<Real(int, int)> rec = [&](int left, int right) {
      int mid = (left + right) >> 1;
      Real x_mid = ps[mid].x, d = LINF;
      if (left + 1 < mid) chmin(d, rec(left, mid));
      if (mid + 1 < right) chmin(d, rec(mid, right));
      inplace_merge(ps.begin() + left, ps.begin() + mid, ps.begin() + right, [&](const Point &a, const Point &b) { return sgn(b.y - a.y) == 1; });
      vector<Point> tmp;
      FOR(i, left, right) {
        if (sgn(abs(ps[i].x - x_mid) - d) == 1) continue;
        for (int j = static_cast<int>(tmp.size()) - 1; j >= 0; --j) {
          Point now = ps[i] - tmp[j];
          if (sgn(now.y - d) == 1) break;
          chmin(d, now.abs());
        }
        tmp.emplace_back(ps[i]);
      }
      return d;
    };
    return rec(0, n);
  }

  Point projection(const Segment &a, const Point &b) { return a.s + (a.t - a.s) * dot(a.t - a.s, b - a.s) / (a.t - a.s).norm(); }
  Point reflection(const Segment &a, const Point &b) { return projection(a, b) * 2 - b; }

  bool is_parallel(const Segment &a, const Segment &b) { return sgn(cross(a.t - a.s, b.t - b.s)) == 0; }
  bool is_orthogonal(const Segment &a, const Segment &b) { return sgn(dot(a.t - a.s, b.t - b.s)) == 0; }

  Real distance(const Point&, const Point&);
  Real distance(const Segment&, const Point&);
  Real distance(const Line&, const Point&);
  int sizeof_common_tangent(const Circle&, const Circle&);
  bool has_intersected(const Segment &a, const Point &b) { return ccw(a.s, a.t, b) == 0; }
  bool has_intersected(const Segment &a, const Segment &b) { return ccw(a.s, a.t, b.s) * ccw(a.s, a.t, b.t) <= 0 && ccw(b.s, b.t, a.s) * ccw(b.s, b.t, a.t) <= 0; }
  bool has_intersected(const Line &a, const Point &b) { int c = ccw(a.s, a.t, b); return c != 1 && c != -1; }
  bool has_intersected(const Line &a, const Segment &b) { return ccw(a.s, a.t, b.s) * ccw(a.s, a.t, b.t) != 1; }
  bool has_intersected(const Line &a, const Line &b) { return sgn(cross(a.t - a.s, b.t - b.s)) != 0 || sgn(cross(a.t - a.s, b.s - a.s)) == 0; }
  bool has_intersected(const Circle &a, const Point &b) { return sgn(distance(a.p, b) - a.r) == 0; }
  bool has_intersected(const Circle &a, const Segment &b) { return sgn(a.r - distance(b, a.p)) != -1 && sgn(max(distance(a.p, b.s), distance(a.p, b.t)) - a.r) != -1; }
  bool has_intersected(const Circle &a, const Line &b) { return sgn(a.r - distance(b, a.p)) != -1; }
  bool has_intersected(const Circle &a, const Circle &b) { return sizeof_common_tangent(a, b) > 0; }

  Point intersection(const Line &a, const Line &b) {
    assert(has_intersected(a, b) && !is_parallel(a, b));
    return a.s + (a.t - a.s) * cross(b.t - b.s, b.s - a.s) / cross(b.t - b.s, a.t - a.s);
  }
  Point intersection(const Segment &a, const Segment &b) {
    assert(has_intersected(a, b));
    if (is_parallel(a, b)) {
      if (sgn(distance(a.s, b.s)) == 0) {
        assert(sgn(dot(a.t - a.s, b.t - a.s)) == -1);
        return a.s;
      } else if (sgn(distance(a.s, b.t)) == 0) {
        assert(sgn(dot(a.t - a.s, b.s - a.s)) == -1);
        return a.s;
      } else if (sgn(distance(a.t, b.s)) == 0) {
        assert(sgn(dot(a.s - a.t, b.t - a.t)) == -1);
        return a.t;
      } else if (sgn(distance(a.t, b.t)) == 0) {
        assert(sgn(dot(a.s - a.t, b.s - a.t)) == -1);
        return a.t;
      } else {
        assert(false);
      }
    } else {
      return intersection(Line(a.s, a.t), Line(b.s, b.t));
    }
  }
  Point intersection(const Line &a, const Segment &b) {
    assert(has_intersected(a, b));
    return intersection(a, Line(b.s, b.t));
  }
  vector<Point> intersection(const Circle &a, const Line &b) {
    Point pro = projection(b, a.p);
    Real nor = (a.p - pro).norm();
    int sign = sgn(a.r - sqrt(nor));
    if (sign == -1) return {};
    if (sign == 0) return {pro};
    Point v = (b.t - b.s).unit_vector() * sqrt(a.r * a.r - nor);
    return {pro + v, pro - v};
  }
  vector<Point> intersection(const Circle &a, const Segment &b) {
    if (!has_intersected(a, b)) return {};
    vector<Point> res = intersection(a, Line(b.s, b.t));
    if (sgn(distance(a.p, b.s) - a.r) != -1 && sgn(distance(a.p, b.t) - a.r) != -1) return res;
    return {sgn(dot(res[0] - b.s, res[0] - b.t)) == 1 ? res[1] : res[0]};
  }
  vector<Point> intersection(const Circle &a, const Circle &b) {
    int sz = sizeof_common_tangent(a, b);
    if (sz == 0 || sz == 4) return {};
    Real alpha = (b.p - a.p).arg();
    if (sz == 1 || sz == 3) return {Point(a.p.x + a.r * cos(alpha), a.p.y + a.r * sin(alpha))};
    Real dist = (b.p - a.p).norm(), beta = acos((dist + a.r * a.r - b.r * b.r) / (2 * sqrt(dist) * a.r));
    return {a.p + Point(a.r * cos(alpha + beta), a.r * sin(alpha + beta)), a.p + Point(a.r * cos(alpha - beta), a.r * sin(alpha - beta))};
  }

  Real distance(const Point &a, const Point &b) { return (b - a).abs(); }
  Real distance(const Segment &a, const Point &b) {
    Point foot = projection(a, b);
    return has_intersected(a, foot) ? distance(foot, b) : min(distance(a.s, b), distance(a.t, b));
  }
  Real distance(const Segment &a, const Segment &b) { return has_intersected(a, b) ? 0 : min({distance(a, b.s), distance(a, b.t), distance(b, a.s), distance(b, a.t)}); }
  Real distance(const Line &a, const Point &b) { return distance(projection(a, b), b); }
  Real distance(const Line &a, const Segment &b) { return has_intersected(a, b) ? 0 : min(distance(a, b.s), distance(a, b.t)); }
  Real distance(const Line &a, const Line &b) { return has_intersected(a, b) ? 0 : distance(a, b.s); }

  vector<Point> tangency(const Circle &a, const Point &b) {
    Real dist = distance(a.p, b);
    int sign = sgn(dist - a.r);
    if (sign == -1) return {};
    if (sign == 0) return {b};
    Real alpha = (b - a.p).arg(), beta = acos(a.r / dist);
    return {a.p + Point(a.r * cos(alpha + beta), a.r * sin(alpha + beta)), a.p + Point(a.r * cos(alpha - beta), a.r * sin(alpha - beta))};
  }
  int sizeof_common_tangent(const Circle &a, const Circle &b) {
    Real dist = distance(a.p, b.p);
    int sign = sgn(a.r + b.r - dist);
    if (sign == -1) return 4;
    if (sign == 0) return 3;
    sign = sgn((sgn(a.r - b.r) == -1 ? b.r - a.r : a.r - b.r) - dist);
    if (sign == -1) return 2;
    if (sign == 0) return 1;
    return 0;
  }
  vector<Line> common_tangent(const Circle &a, const Circle &b) {
    vector<Line> tangents;
    Real dist = distance(a.p, b.p), argument = (b.p - a.p).arg();
    int sign = sgn(a.r + b.r - dist);
    if (sign == -1) {
      Real ac = acos((a.r + b.r) / dist), alpha = argument + ac, cs = cos(alpha), sn = sin(alpha);
      tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
      alpha = argument - ac; cs = cos(alpha); sn = sin(alpha);
      tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
    } else if (sign == 0) {
      Point s = a.p + Point(a.r * cos(argument), a.r * sin(argument));
      tangents.emplace_back(s, s + (b.p - a.p).normal_unit_vector().first);
    }
    if (sgn(b.r - a.r) == -1) {
      sign = sgn(a.r - b.r - dist);
      if (sign == -1) {
        Real at = acos((a.r - b.r) / dist), alpha = argument + at, cs = cos(alpha), sn = sin(alpha);
        tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(b.r * cs, b.r * sn));
        alpha = argument - at; cs = cos(alpha); sn = sin(alpha);
        tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(b.r * cs, b.r * sn));
      } else if (sign == 0) {
        Point s = a.p + Point(a.r * cos(argument), a.r * sin(argument));
        tangents.emplace_back(s, s + (b.p - a.p).normal_unit_vector().first);
      }
    } else {
      sign = sgn(b.r - a.r - dist);
      if (sign == -1) {
        Real at = acos((b.r - a.r) / dist), alpha = argument - at, cs = cos(alpha), sn = sin(alpha);
        tangents.emplace_back(a.p + Point(-a.r * cs, -a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
        alpha = argument + at; cs = cos(alpha); sn = sin(alpha);
        tangents.emplace_back(a.p + Point(-a.r * cs, -a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
      } else if (sign == 0) {
        Point s = b.p + Point(-b.r * cos(argument), -b.r * sin(argument));
        tangents.emplace_back(s, s + (a.p - b.p).normal_unit_vector().first);
      }
    }
    return tangents;
  }

  Real intersection_area(const Circle &a, const Circle &b) {
    Real nor = (b.p - a.p).norm(), dist = sqrt(nor);
    if (sgn(a.r + b.r - dist) != 1) return 0;
    if (sgn(abs(a.r - b.r) - dist) != -1) return min(a.r, b.r) * min(a.r, b.r) * M_PI;
    Real alpha = acos((nor + a.r * a.r - b.r * b.r) / (2 * dist * a.r)), beta = acos((nor + b.r * b.r - a.r * a.r) / (2 * dist * b.r));
    return (alpha - sin(alpha + alpha) * 0.5) * a.r * a.r + (beta - sin(beta + beta) * 0.5) * b.r * b.r;
  }

  using Polygon = vector<Point>;

  Real area(const Polygon &a) {
    int n = a.size();
    Real res = 0;
    REP(i, n) res += cross(a[i], a[(i + 1) % n]);
    return res * 0.5;
  }

  Point centroid(const Polygon &a) {
    Point res(0, 0);
    int n = a.size();
    Real den = 0;
    REP(i, n) {
      Real cro = cross(a[i], a[(i + 1) % n]);
      res += (a[i] + a[(i + 1) % n]) / 3 * cro;
      den += cro;
    }
    return res / den;
  }

  int is_contained(const Polygon &a, const Point &b) {
    int n = a.size();
    bool is_in = false;
    REP(i, n) {
      Point p = a[i] - b, q = a[(i + 1) % n] - b;
      if (sgn(q.y - p.y) == -1) swap(p, q);
      int sign = sgn(cross(p, q));
      if (sign == 1 && sgn(p.y) != 1 && sgn(q.y) == 1) is_in = !is_in;
      if (sign == 0 && sgn(dot(p, q)) != 1) return 1;
    }
    return is_in ? 2 : 0;
  }

  bool is_convex(const Polygon &a) {
    int n = a.size();
    REP(i, n) {
      if (ccw(a[(i - 1 + n) % n], a[i], a[(i + 1) % n]) == -1) return false;
    }
    return true;
  }

  Polygon monotone_chain(vector<Point> ps, bool tight = true) {
    sort(ALL(ps));
    int n = ps.size(), idx = 0;
    Polygon convex_hull(n << 1);
    for (int i = 0; i < n; convex_hull[idx++] = ps[i++]) {
      while (idx >= 2 && sgn(cross(convex_hull[idx - 1] - convex_hull[idx - 2], ps[i] - convex_hull[idx - 1])) < tight) --idx;
    }
    for (int i = n - 2, border = idx + 1; i >= 0; convex_hull[idx++] = ps[i--]) {
      while (idx >= border && sgn(cross(convex_hull[idx - 1] - convex_hull[idx - 2], ps[i] - convex_hull[idx - 1])) < tight) --idx;
    }
    convex_hull.resize(idx - 1);
    return convex_hull;
  }

  Polygon cut_convex(const Polygon &a, const Line &b) {
    int n = a.size();
    Polygon res;
    REP(i, n) {
      int c = ccw(b.s, b.t, a[i]);
      if (c != -1) res.emplace_back(a[i]);
      if (c * ccw(b.s, b.t, a[(i + 1) % n]) == -1) res.emplace_back(intersection(Line(a[i], a[(i + 1) % n]), b));
    }
    if (res.size() < 3) res.clear();
    return res;
  }

  pair<Point, Point> rotating_calipers(const Polygon &a) {
    int n = a.size(), high = 0, low = 0;
    if (n <= 2) {
      assert(n == 2);
      return {a[0], a[1]};
    }
    FOR(i, 1, n) {
      if (a[i].y > a[high].y) high = i;
      if (a[i].y < a[low].y) low = i;
    }
    Real max_norm = (a[high] - a[low]).norm();
    int i = high, j = low, max_i = i, max_j = j;
    do {
      ((sgn(cross(a[(i + 1) % n] - a[i], a[(j + 1) % n] - a[j])) != -1 ? j : i) += 1) %= n;
      Real tmp = (a[j] - a[i]).norm();
      if (sgn(tmp - max_norm) == 1) {
        max_norm = tmp;
        max_i = i; max_j = j;
      }
    } while (i != high || j != low);
    return {a[max_i], a[max_j]};
  }
}

using namespace Geometry;

int main() {
  int n, k; cin >> n >> k;
  vector<Circle> people;
  REP(_, n) {
    Point p; double r; cin >> p >> r;
    people.emplace_back(p, r);
  }
  vector<double> l(n), r(n), comp;
  REP(i, n) {
    vector<Point> t = tangency(people[i], Point(0, 0));
    l[i] = t[0].arg(); r[i] = t[1].arg();
    if (l[i] > r[i]) swap(l[i], r[i]);
    if (r[i] > M_PI && has_intersected(people[i], Segment(Point(0, 0), Point(2415, 0)))) {
      swap(l[i], r[i]);
      l[i] = 0;
    } else {
      chmax(l[i], 0);
      chmin(r[i], M_PI);
    }
    if (l[i] < M_PI) {
      comp.emplace_back(l[i]);
      comp.emplace_back(r[i]);
    }
  }
  vector<bool> use(n, true);
  REP(i, n) {
    if (l[i] >= M_PI) use[i] = false;
    if (!use[i]) continue;
    REP(j, n) {
      if (j != i && l[i] <= l[j] && r[j] <= r[i]) use[j] = false;
    }
  }
  vector<pair<double, double>> ball;
  REP(i, n) {
    if (use[i]) ball.emplace_back(l[i], r[i]);
  }
  n = ball.size();
  if (n == 0) {
    cout << "0\n";
    return 0;
  }
  sort(ALL(ball));
  // REP(i, n) cout << ball[i].first << ' ' << ball[i].second << '\n';
  vector<vector<vector<double>>> dp(n, vector<vector<double>>(k + 1, vector<double>(2, -INF)));
  dp[0][0][false] = 0;
  dp[0][1][true] = ball[0].second - ball[0].first;
  FOR(i, 1, n) {
    double left, right; tie(left, right) = ball[i];
    int x = i - 1;
    while (x >= 0 && ball[i].first <= ball[x].second) --x;
    ++x;
    chmin(x, i - 1);
    REP(j, k + 1) {
      if (j + 1 <= k) {
        chmax(dp[i][j + 1][true], dp[x][j][true] + right - max(ball[x].second, left));
        chmax(dp[i][j + 1][true], dp[x][j][false] + right - left);
      }
      chmax(dp[i][j][false], max(dp[i - 1][j][false], dp[i - 1][j][true]));
    }
  }
  double ans = 0;
  REP(y, k + 1) REP(z, 2) chmax(ans, dp[n - 1][y][z]);
  cout << ans / M_PI << '\n';
  return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 127048
final_rank: 15

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007;
// const int MOD = 998244353;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
const int dy8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx8[] = {0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} iosetup;

namespace Geometry {
  using Real = double;

  int sgn(Real x) { return x > EPS ? 1 : x < -EPS ? -1 : 0; }

  Real degree_to_radian(Real d) { return d * M_PI / 180; }
  Real radian_to_degree(Real r) { return r * 180 / M_PI; }

  struct Point {
    Real x, y;
    Point(Real x = 0, Real y = 0) : x(x), y(y) {}
    Real abs() const { return sqrt(norm()); }
    Real arg() const { Real res = atan2(y, x); return res < 0 ? res + M_PI * 2 : res; }
    Real norm() const { return x * x + y * y; }
    Point rotate(Real angle) const { Real cs = cos(angle), sn = sin(angle); return Point(x * cs - y * sn, x * sn + y * cs); }
    Point unit_vector() const { Real a = abs(); return Point(x / a, y / a); }
    pair<Point, Point> normal_unit_vector() const { Point p = unit_vector(); return {Point(-p.y, p.x), Point(p.y, -p.x)}; }
    Point &operator+=(const Point &p) { x += p.x; y += p.y; return *this; }
    Point &operator-=(const Point &p) { x -= p.x; y -= p.y; return *this; }
    Point &operator*=(Real k) { x *= k; y *= k; return *this; }
    Point &operator/=(Real k) { x /= k; y /= k; return *this; }
    bool operator<(const Point &p) const { int x_sgn = sgn(p.x - x); return x_sgn != 0 ? x_sgn == 1 : sgn(p.y - y) == 1; }
    bool operator<=(const Point &p) const { return !(p < *this); }
    bool operator>(const Point &p) const { return p < *this; }
    bool operator>=(const Point &p) const { return !(*this < p); }
    Point operator+() const { return *this; }
    Point operator-() const { return Point(-x, -y); }
    Point operator+(const Point &p) const { return Point(*this) += p; }
    Point operator-(const Point &p) const { return Point(*this) -= p; }
    Point operator*(Real k) const { return Point(*this) *= k; }
    Point operator/(Real k) const { return Point(*this) /= k; }
    friend ostream &operator<<(ostream &os, const Point &p) { return os << '(' << p.x << ", " << p.y << ')'; }
    friend istream &operator>>(istream &is, Point &p) { Real x, y; is >> x >> y; p = Point(x, y); return is; }
  };

  struct Segment {
    Point s, t;
    Segment(const Point &s = {0, 0}, const Point &t = {0, 0}) : s(s), t(t) {}
  };
  struct Line : Segment {
    using Segment::Segment;
    Line(Real a, Real b, Real c) {
      if (sgn(a) == 0) {
        s = Point(0, -c / b); t = Point(1, s.y);
      } else if (sgn(b) == 0) {
        s = Point(-c / a, 0); t = Point(s.x, 1);
      } else if (sgn(c) == 0) {
        s = Point(0, 0); t = Point(1, -a / b);
      } else {
        s = Point(0, -c / b); t = Point(-c / a, 0);
      }
    }
  };

  struct Circle {
    Point p; Real r;
    Circle(const Point &p = {0, 0}, Real r = 0) : p(p), r(r) {}
  };

  Real cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }
  Real dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }

  int ccw(const Point &a, const Point &b, const Point &c) {
    Point ab = b - a, ac = c - a;
    int sign = sgn(cross(ab, ac));
    if (sign == 0) {
      if (sgn(dot(ab, ac)) == -1) return 2;
      if (sgn(ac.norm() - ab.norm()) == 1) return -2;
    }
    return sign;
  }

  Real get_angle(const Point &a, const Point &b, const Point &c) {
    Real ba_arg = (a - b).arg(), bc_arg = (c - b).arg();
    if (ba_arg > bc_arg) swap(ba_arg, bc_arg);
    return min(bc_arg - ba_arg, M_PI * 2 - (bc_arg - ba_arg));
  }

  Real closest_pair(vector<Point> ps) {
    int n = ps.size();
    assert(n > 1);
    sort(ALL(ps));
    function<Real(int, int)> rec = [&](int left, int right) {
      int mid = (left + right) >> 1;
      Real x_mid = ps[mid].x, d = LINF;
      if (left + 1 < mid) chmin(d, rec(left, mid));
      if (mid + 1 < right) chmin(d, rec(mid, right));
      inplace_merge(ps.begin() + left, ps.begin() + mid, ps.begin() + right, [&](const Point &a, const Point &b) { return sgn(b.y - a.y) == 1; });
      vector<Point> tmp;
      FOR(i, left, right) {
        if (sgn(abs(ps[i].x - x_mid) - d) == 1) continue;
        for (int j = static_cast<int>(tmp.size()) - 1; j >= 0; --j) {
          Point now = ps[i] - tmp[j];
          if (sgn(now.y - d) == 1) break;
          chmin(d, now.abs());
        }
        tmp.emplace_back(ps[i]);
      }
      return d;
    };
    return rec(0, n);
  }

  Point projection(const Segment &a, const Point &b) { return a.s + (a.t - a.s) * dot(a.t - a.s, b - a.s) / (a.t - a.s).norm(); }
  Point reflection(const Segment &a, const Point &b) { return projection(a, b) * 2 - b; }

  bool is_parallel(const Segment &a, const Segment &b) { return sgn(cross(a.t - a.s, b.t - b.s)) == 0; }
  bool is_orthogonal(const Segment &a, const Segment &b) { return sgn(dot(a.t - a.s, b.t - b.s)) == 0; }

  Real distance(const Point&, const Point&);
  Real distance(const Segment&, const Point&);
  Real distance(const Line&, const Point&);
  int sizeof_common_tangent(const Circle&, const Circle&);
  bool has_intersected(const Segment &a, const Point &b) { return ccw(a.s, a.t, b) == 0; }
  bool has_intersected(const Segment &a, const Segment &b) { return ccw(a.s, a.t, b.s) * ccw(a.s, a.t, b.t) <= 0 && ccw(b.s, b.t, a.s) * ccw(b.s, b.t, a.t) <= 0; }
  bool has_intersected(const Line &a, const Point &b) { int c = ccw(a.s, a.t, b); return c != 1 && c != -1; }
  bool has_intersected(const Line &a, const Segment &b) { return ccw(a.s, a.t, b.s) * ccw(a.s, a.t, b.t) != 1; }
  bool has_intersected(const Line &a, const Line &b) { return sgn(cross(a.t - a.s, b.t - b.s)) != 0 || sgn(cross(a.t - a.s, b.s - a.s)) == 0; }
  bool has_intersected(const Circle &a, const Point &b) { return sgn(distance(a.p, b) - a.r) == 0; }
  bool has_intersected(const Circle &a, const Segment &b) { return sgn(a.r - distance(b, a.p)) != -1 && sgn(max(distance(a.p, b.s), distance(a.p, b.t)) - a.r) != -1; }
  bool has_intersected(const Circle &a, const Line &b) { return sgn(a.r - distance(b, a.p)) != -1; }
  bool has_intersected(const Circle &a, const Circle &b) { return sizeof_common_tangent(a, b) > 0; }

  Point intersection(const Line &a, const Line &b) {
    assert(has_intersected(a, b) && !is_parallel(a, b));
    return a.s + (a.t - a.s) * cross(b.t - b.s, b.s - a.s) / cross(b.t - b.s, a.t - a.s);
  }
  Point intersection(const Segment &a, const Segment &b) {
    assert(has_intersected(a, b));
    if (is_parallel(a, b)) {
      if (sgn(distance(a.s, b.s)) == 0) {
        assert(sgn(dot(a.t - a.s, b.t - a.s)) == -1);
        return a.s;
      } else if (sgn(distance(a.s, b.t)) == 0) {
        assert(sgn(dot(a.t - a.s, b.s - a.s)) == -1);
        return a.s;
      } else if (sgn(distance(a.t, b.s)) == 0) {
        assert(sgn(dot(a.s - a.t, b.t - a.t)) == -1);
        return a.t;
      } else if (sgn(distance(a.t, b.t)) == 0) {
        assert(sgn(dot(a.s - a.t, b.s - a.t)) == -1);
        return a.t;
      } else {
        assert(false);
      }
    } else {
      return intersection(Line(a.s, a.t), Line(b.s, b.t));
    }
  }
  Point intersection(const Line &a, const Segment &b) {
    assert(has_intersected(a, b));
    return intersection(a, Line(b.s, b.t));
  }
  vector<Point> intersection(const Circle &a, const Line &b) {
    Point pro = projection(b, a.p);
    Real nor = (a.p - pro).norm();
    int sign = sgn(a.r - sqrt(nor));
    if (sign == -1) return {};
    if (sign == 0) return {pro};
    Point v = (b.t - b.s).unit_vector() * sqrt(a.r * a.r - nor);
    return {pro + v, pro - v};
  }
  vector<Point> intersection(const Circle &a, const Segment &b) {
    if (!has_intersected(a, b)) return {};
    vector<Point> res = intersection(a, Line(b.s, b.t));
    if (sgn(distance(a.p, b.s) - a.r) != -1 && sgn(distance(a.p, b.t) - a.r) != -1) return res;
    return {sgn(dot(res[0] - b.s, res[0] - b.t)) == 1 ? res[1] : res[0]};
  }
  vector<Point> intersection(const Circle &a, const Circle &b) {
    int sz = sizeof_common_tangent(a, b);
    if (sz == 0 || sz == 4) return {};
    Real alpha = (b.p - a.p).arg();
    if (sz == 1 || sz == 3) return {Point(a.p.x + a.r * cos(alpha), a.p.y + a.r * sin(alpha))};
    Real dist = (b.p - a.p).norm(), beta = acos((dist + a.r * a.r - b.r * b.r) / (2 * sqrt(dist) * a.r));
    return {a.p + Point(a.r * cos(alpha + beta), a.r * sin(alpha + beta)), a.p + Point(a.r * cos(alpha - beta), a.r * sin(alpha - beta))};
  }

  Real distance(const Point &a, const Point &b) { return (b - a).abs(); }
  Real distance(const Segment &a, const Point &b) {
    Point foot = projection(a, b);
    return has_intersected(a, foot) ? distance(foot, b) : min(distance(a.s, b), distance(a.t, b));
  }
  Real distance(const Segment &a, const Segment &b) { return has_intersected(a, b) ? 0 : min({distance(a, b.s), distance(a, b.t), distance(b, a.s), distance(b, a.t)}); }
  Real distance(const Line &a, const Point &b) { return distance(projection(a, b), b); }
  Real distance(const Line &a, const Segment &b) { return has_intersected(a, b) ? 0 : min(distance(a, b.s), distance(a, b.t)); }
  Real distance(const Line &a, const Line &b) { return has_intersected(a, b) ? 0 : distance(a, b.s); }

  vector<Point> tangency(const Circle &a, const Point &b) {
    Real dist = distance(a.p, b);
    int sign = sgn(dist - a.r);
    if (sign == -1) return {};
    if (sign == 0) return {b};
    Real alpha = (b - a.p).arg(), beta = acos(a.r / dist);
    return {a.p + Point(a.r * cos(alpha + beta), a.r * sin(alpha + beta)), a.p + Point(a.r * cos(alpha - beta), a.r * sin(alpha - beta))};
  }
  int sizeof_common_tangent(const Circle &a, const Circle &b) {
    Real dist = distance(a.p, b.p);
    int sign = sgn(a.r + b.r - dist);
    if (sign == -1) return 4;
    if (sign == 0) return 3;
    sign = sgn((sgn(a.r - b.r) == -1 ? b.r - a.r : a.r - b.r) - dist);
    if (sign == -1) return 2;
    if (sign == 0) return 1;
    return 0;
  }
  vector<Line> common_tangent(const Circle &a, const Circle &b) {
    vector<Line> tangents;
    Real dist = distance(a.p, b.p), argument = (b.p - a.p).arg();
    int sign = sgn(a.r + b.r - dist);
    if (sign == -1) {
      Real ac = acos((a.r + b.r) / dist), alpha = argument + ac, cs = cos(alpha), sn = sin(alpha);
      tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
      alpha = argument - ac; cs = cos(alpha); sn = sin(alpha);
      tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
    } else if (sign == 0) {
      Point s = a.p + Point(a.r * cos(argument), a.r * sin(argument));
      tangents.emplace_back(s, s + (b.p - a.p).normal_unit_vector().first);
    }
    if (sgn(b.r - a.r) == -1) {
      sign = sgn(a.r - b.r - dist);
      if (sign == -1) {
        Real at = acos((a.r - b.r) / dist), alpha = argument + at, cs = cos(alpha), sn = sin(alpha);
        tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(b.r * cs, b.r * sn));
        alpha = argument - at; cs = cos(alpha); sn = sin(alpha);
        tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(b.r * cs, b.r * sn));
      } else if (sign == 0) {
        Point s = a.p + Point(a.r * cos(argument), a.r * sin(argument));
        tangents.emplace_back(s, s + (b.p - a.p).normal_unit_vector().first);
      }
    } else {
      sign = sgn(b.r - a.r - dist);
      if (sign == -1) {
        Real at = acos((b.r - a.r) / dist), alpha = argument - at, cs = cos(alpha), sn = sin(alpha);
        tangents.emplace_back(a.p + Point(-a.r * cs, -a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
        alpha = argument + at; cs = cos(alpha); sn = sin(alpha);
        tangents.emplace_back(a.p + Point(-a.r * cs, -a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
      } else if (sign == 0) {
        Point s = b.p + Point(-b.r * cos(argument), -b.r * sin(argument));
        tangents.emplace_back(s, s + (a.p - b.p).normal_unit_vector().first);
      }
    }
    return tangents;
  }

  Real intersection_area(const Circle &a, const Circle &b) {
    Real nor = (b.p - a.p).norm(), dist = sqrt(nor);
    if (sgn(a.r + b.r - dist) != 1) return 0;
    if (sgn(abs(a.r - b.r) - dist) != -1) return min(a.r, b.r) * min(a.r, b.r) * M_PI;
    Real alpha = acos((nor + a.r * a.r - b.r * b.r) / (2 * dist * a.r)), beta = acos((nor + b.r * b.r - a.r * a.r) / (2 * dist * b.r));
    return (alpha - sin(alpha + alpha) * 0.5) * a.r * a.r + (beta - sin(beta + beta) * 0.5) * b.r * b.r;
  }

  using Polygon = vector<Point>;

  Real area(const Polygon &a) {
    int n = a.size();
    Real res = 0;
    REP(i, n) res += cross(a[i], a[(i + 1) % n]);
    return res * 0.5;
  }

  Point centroid(const Polygon &a) {
    Point res(0, 0);
    int n = a.size();
    Real den = 0;
    REP(i, n) {
      Real cro = cross(a[i], a[(i + 1) % n]);
      res += (a[i] + a[(i + 1) % n]) / 3 * cro;
      den += cro;
    }
    return res / den;
  }

  int is_contained(const Polygon &a, const Point &b) {
    int n = a.size();
    bool is_in = false;
    REP(i, n) {
      Point p = a[i] - b, q = a[(i + 1) % n] - b;
      if (sgn(q.y - p.y) == -1) swap(p, q);
      int sign = sgn(cross(p, q));
      if (sign == 1 && sgn(p.y) != 1 && sgn(q.y) == 1) is_in = !is_in;
      if (sign == 0 && sgn(dot(p, q)) != 1) return 1;
    }
    return is_in ? 2 : 0;
  }

  bool is_convex(const Polygon &a) {
    int n = a.size();
    REP(i, n) {
      if (ccw(a[(i - 1 + n) % n], a[i], a[(i + 1) % n]) == -1) return false;
    }
    return true;
  }

  Polygon monotone_chain(vector<Point> ps, bool tight = true) {
    sort(ALL(ps));
    int n = ps.size(), idx = 0;
    Polygon convex_hull(n << 1);
    for (int i = 0; i < n; convex_hull[idx++] = ps[i++]) {
      while (idx >= 2 && sgn(cross(convex_hull[idx - 1] - convex_hull[idx - 2], ps[i] - convex_hull[idx - 1])) < tight) --idx;
    }
    for (int i = n - 2, border = idx + 1; i >= 0; convex_hull[idx++] = ps[i--]) {
      while (idx >= border && sgn(cross(convex_hull[idx - 1] - convex_hull[idx - 2], ps[i] - convex_hull[idx - 1])) < tight) --idx;
    }
    convex_hull.resize(idx - 1);
    return convex_hull;
  }

  Polygon cut_convex(const Polygon &a, const Line &b) {
    int n = a.size();
    Polygon res;
    REP(i, n) {
      int c = ccw(b.s, b.t, a[i]);
      if (c != -1) res.emplace_back(a[i]);
      if (c * ccw(b.s, b.t, a[(i + 1) % n]) == -1) res.emplace_back(intersection(Line(a[i], a[(i + 1) % n]), b));
    }
    if (res.size() < 3) res.clear();
    return res;
  }

  pair<Point, Point> rotating_calipers(const Polygon &a) {
    int n = a.size(), high = 0, low = 0;
    if (n <= 2) {
      assert(n == 2);
      return {a[0], a[1]};
    }
    FOR(i, 1, n) {
      if (a[i].y > a[high].y) high = i;
      if (a[i].y < a[low].y) low = i;
    }
    Real max_norm = (a[high] - a[low]).norm();
    int i = high, j = low, max_i = i, max_j = j;
    do {
      ((sgn(cross(a[(i + 1) % n] - a[i], a[(j + 1) % n] - a[j])) != -1 ? j : i) += 1) %= n;
      Real tmp = (a[j] - a[i]).norm();
      if (sgn(tmp - max_norm) == 1) {
        max_norm = tmp;
        max_i = i; max_j = j;
      }
    } while (i != high || j != low);
    return {a[max_i], a[max_j]};
  }
}

using namespace Geometry;

int main() {
  int n, k; cin >> n >> k;
  vector<Circle> people;
  REP(_, n) {
    Point p; double r; cin >> p >> r;
    people.emplace_back(p, r);
  }
  vector<double> l(n), r(n), comp;
  REP(i, n) {
    vector<Point> t = tangency(people[i], Point(0, 0));
    l[i] = t[0].arg(); r[i] = t[1].arg();
    if (l[i] > r[i]) swap(l[i], r[i]);
    if (r[i] > M_PI && has_intersected(people[i], Segment(Point(0, 0), Point(2415, 0)))) {
      swap(l[i], r[i]);
      l[i] = 0;
    } else {
      chmax(l[i], 0);
      chmin(r[i], M_PI);
    }
    if (l[i] < M_PI) {
      comp.emplace_back(l[i]);
      comp.emplace_back(r[i]);
    }
  }
  vector<bool> use(n, true);
  REP(i, n) {
    if (l[i] >= M_PI) use[i] = false;
    REP(j, n) {
      if (j != i && l[i] <= l[j] && r[j] <= r[i]) use[j] = false;
    }
  }
  vector<pair<double, double>> ball;
  REP(i, n) {
    if (use[i]) ball.emplace_back(l[i], r[i]);
  }
  n = ball.size();
  sort(ALL(ball));
  // REP(i, n) cout << ball[i].first << ' ' << ball[i].second << '\n';
  vector<vector<vector<double>>> dp(n, vector<vector<double>>(k + 1, vector<double>(2, -INF)));
  dp[0][0][false] = 0;
  dp[0][1][true] = ball[0].second - ball[0].first;
  FOR(i, 1, n) {
    double left, right; tie(left, right) = ball[i];
    int x = i - 1;
    while (x >= 0 && ball[i].first <= ball[x].second) --x;
    ++x;
    chmin(x, i - 1);
    REP(j, k + 1) {
      if (j + 1 <= k) {
        chmax(dp[i][j + 1][true], dp[x][j][true] + right - max(ball[x].second, left));
        chmax(dp[i][j + 1][true], dp[x][j][false] + right - left);
      }
      chmax(dp[i][j][false], max(dp[i - 1][j][false], dp[i - 1][j][true]));
    }
  }
  double ans = 0;
  REP(y, k + 1) REP(z, 2) chmax(ans, dp[n - 1][y][z]);
  cout << ans / M_PI << '\n';
  return 0;
}
accuracy: 0.8028169014084507
time_ms: 40
memory_kb: 47752
final_rank: 16

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 1505

struct Point{
    Point(double arg_x,double arg_y){
        x = arg_x;
        y = arg_y;
    }

    Point(){
        x = y = 0.0;
    }

    Point operator + (Point p){ return Point(x+p.x,y+p.y); }
    Point operator - (Point p){ return Point(x-p.x,y-p.y);}
    Point operator * (double a){ return Point(a*x,a*y); }
    Point operator / (double a){ return Point(x/a,y/a); }

    double abs(){ return sqrt(norm()); }
    double norm(){ return x*x + y*y; }

    bool operator<(const Point &p) const{
        return x != p.x? x < p.x: y < p.y;
    }

    bool operator == (const Point &p) const{
        return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
    }

    double x,y;
};

typedef Point Vector;

struct Sphere{
    Point center;
    double r;
};

typedef Sphere Circle;

struct Line{
public:
    Point p[2];
    Line(Point p1,Point p2){
        p[0] = p1;
        p[1] = p2;
    }
    Line(){

    }
};

struct Info{
	bool operator<(const struct Info &arg) const{

		return left > arg.left;
	}
	double left,right;
};

int N,K;
int most_L[SIZE];
vector<Info> work,V;
double dp1[SIZE][SIZE],dp2[SIZE][SIZE];
Circle circle[SIZE];


double NUM = 10000;

double norm(Vector a){
    return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
    return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

Point project(Line l,Point p){

    Vector base = l.p[1]-l.p[0];
    double r = dot(p-l.p[0],base)/norm(base);
    return l.p[0]+base*r;
}

//円と直線の交点を求める関数
vector<Point> getCrossPoints(Circle c,Line l){

    vector<Point> ret;

    Vector pr = project(l,c.center);
    Vector e = (l.p[1]-l.p[0])/abs(l.p[1]-l.p[0]);

    double base;

    if(fabs(c.r*c.r-norm(pr-c.center)) < EPS){

        base = 0;
    }else{
        base = sqrt(c.r*c.r-norm(pr-c.center));
    }

    ret.push_back(Point(pr+e*base));
    ret.push_back(Point(pr-e*base));

    return ret;
}

double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

int calc_area(double deg){

	if(deg >= 0 && deg <= 90){

		return 1;
	}else if(deg <= 180){

		return 2;
	}else if(deg <= 270){

		return 3;
	}else{

		return 4;
	}
}

int main(){

	Point base = Point(0,0);

	scanf("%d %d",&N,&K);

	for(int i = 0; i < N; i++){

		scanf("%lf %lf %lf",&circle[i].center.x,&circle[i].center.y,&circle[i].r);
		if(calc_dist(base,circle[i].center) < circle[i].r){

			printf("1.0\n");
			return 0;
		}
	}

	int area1,area2;

	Line line = Line(Point(0,-10000),Point(0,10000));

	vector<Point> P;

	for(int i = 0; i < N; i++){

		double angle1 = atan2(circle[i].center.y,circle[i].center.x)*(180/M_PI);
		if(angle1 < 0){

			angle1 += 360;
		}
		double angle2 = asin(circle[i].r/abs(circle[i].center))*(180/M_PI);
		if(angle2 < 0){

			angle2 += 360;
		}

		double deg1 = angle1+angle2;
		if(deg1 >= 360){

			deg1 -= 360;
		}

		double deg2 = angle1-angle2;
		if(deg2 < 0){

			deg2 += 360;
		}

		area1 = calc_area(deg1);
		area2 = calc_area(deg2);


		if(area1 != 1 && area2 != 1 && area1 !=2 && area2 != 2)continue;

		if(area1 > area2){
			swap(area1,area2);
			swap(deg1,deg2);
		}

		Info info;
		info.right = deg1;

		if(area1 == 1){

			switch(area2){
			case 1:
			case 2:
				info.left = deg2;
				break;
			case 3:
				P = getCrossPoints(circle[i],line); //注意

				if(P[0].y > 0 && P[1].y > 0){

					info.left = 180;

				}else{

					info.left = 0;
				}

				break;
			case 4:
				info.left = 0;
				break;
			}

		}else{ //area1 == 2

			switch(area2){
			case 2:
				info.left = deg2;
				break;
			case 3:
				info.left = 180;
				break;
			case 4:
				P = getCrossPoints(circle[i],line); //注意

				if(P[0].y > 0 && P[1].y > 0){

					info.left = 0;

				}else{

					info.left = 180;
				}
				break;
			}
		}

		if(info.right > info.left){

			swap(info.left,info.right);
		}
		work.push_back(info);
	}

	bool FLG;
	//他でカバーできる接線のペアは除く
	for(int i = 0; i < work.size(); i++){
		FLG = false;
		for(int k = i+1; k < work.size(); k++){
			if(k == i)continue;

			if(work[k].left >= work[i].left && work[k].right <= work[i].right){

				FLG = true;
				break;
			}
		}
		if(!FLG){

			V.push_back(work[i]);
		}
	}

	sort(V.begin(),V.end()); //leftの降順

	for(int i = 0; i < V.size(); i++){
		most_L[i] = -1;
		for(int k = 0; k < i; k++){
			if(V[k].right > V[i].left+EPS)continue;

			most_L[i] = k;
			break;
		}
	}

	for(int i = 0; i <= K; i++){
		for(int k = 0; k <= V.size(); k++){
			dp1[i][k] = 0;
			dp2[i][k] = 0;
		}
	}

	double maximum = 0;

	for(int i = 1; i <= K; i++){ //使用個数
		for(int k = 1; k <= V.size(); k++){ //最後のindex(本来のindex+1)
			if(most_L[k-1] == -1){

				dp1[i][k] = dp2[i-1][k-1]+V[k-1].left-V[k-1].right;

			}else{ //重なりを持つ区間あり

				dp1[i][k] = max(dp1[i-1][most_L[k-1]+1]+V[most_L[k-1]].right-V[k-1].right,
						dp2[i-1][most_L[k-1]]+V[k-1].left-V[k-1].right);
			}
			dp2[i][k] = max(dp1[i][k],dp2[i][k-1]);

			maximum = max(maximum,dp2[i][k]);
		}
	}

	printf("%.10lf\n",maximum/180.0);

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 39032
final_rank: 8

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 1505

struct Point{
    Point(double arg_x,double arg_y){
        x = arg_x;
        y = arg_y;
    }

    Point(){
        x = y = 0.0;
    }

    Point operator + (Point p){ return Point(x+p.x,y+p.y); }
    Point operator - (Point p){ return Point(x-p.x,y-p.y);}
    Point operator * (double a){ return Point(a*x,a*y); }
    Point operator / (double a){ return Point(x/a,y/a); }

    double abs(){ return sqrt(norm()); }
    double norm(){ return x*x + y*y; }

    bool operator<(const Point &p) const{
        return x != p.x? x < p.x: y < p.y;
    }

    bool operator == (const Point &p) const{
        return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
    }

    double x,y;
};

typedef Point Vector;

struct Sphere{
    Point center;
    double r;
};

typedef Sphere Circle;

struct Line{
public:
    Point p[2];
    Line(Point p1,Point p2){
        p[0] = p1;
        p[1] = p2;
    }
    Line(){

    }
};

struct Info{
	bool operator<(const struct Info &arg) const{

		return left > arg.left;
	}
	double left,right;
};

int N,K;
int most_L[SIZE];
vector<Info> work,V;
double dp1[SIZE][SIZE],dp2[SIZE][SIZE];
Circle circle[SIZE];


double NUM = 10000;

double norm(Vector a){
    return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
    return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

Point project(Line l,Point p){

    Vector base = l.p[1]-l.p[0];
    double r = dot(p-l.p[0],base)/norm(base);
    return l.p[0]+base*r;
}

//円と直線の交点を求める関数
vector<Point> getCrossPoints(Circle c,Line l){

    vector<Point> ret;

    Vector pr = project(l,c.center);
    Vector e = (l.p[1]-l.p[0])/abs(l.p[1]-l.p[0]);

    double base;

    if(fabs(c.r*c.r-norm(pr-c.center)) < EPS){

        base = 0;
    }else{
        base = sqrt(c.r*c.r-norm(pr-c.center));
    }

    ret.push_back(Point(pr+e*base));
    ret.push_back(Point(pr-e*base));

    return ret;
}

double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

int calc_area(double deg){

	if(deg >= 0 && deg <= 90){

		return 1;
	}else if(deg <= 180){

		return 2;
	}else if(deg <= 270){

		return 3;
	}else{

		return 4;
	}
}


//第1,第2象限の角度を求める
double calc_angle(Vector vec){

	if(fabs(vec.x) < EPS){

		return 90;
	}
	double ret = atan(fabs(vec.y)/fabs(vec.x))*(180/M_PI);

	if(vec.x < 0){

		ret = 180-ret;
	}
	return ret;
}



int main(){

	Point base = Point(0,0);

	scanf("%d %d",&N,&K);

	for(int i = 0; i < N; i++){

		scanf("%lf %lf %lf",&circle[i].center.x,&circle[i].center.y,&circle[i].r);
		if(calc_dist(base,circle[i].center) < circle[i].r){

			printf("1.0\n");
			return 0;
		}
	}

	int area1,area2;

	Line line = Line(Point(0,-10000),Point(0,10000));

	vector<Point> P;

	for(int i = 0; i < N; i++){

		double angle1 = atan2(circle[i].center.y,circle[i].center.x)*(180/M_PI);
		if(angle1 < 0){

			angle1 += 360;
		}
		double angle2 = asin(circle[i].r/abs(circle[i].center))*(180/M_PI);
		if(angle2 < 0){

			angle2 += 360;
		}

		double deg1 = angle1+angle2;
		if(deg1 >= 360){

			deg1 -= 360;
		}

		double deg2 = angle1-angle2;
		if(deg2 < 0){

			deg2 += 360;
		}

		area1 = calc_area(deg1);
		area2 = calc_area(deg2);


		if(area1 != 1 && area2 != 1 && area1 !=2 && area2 != 2)continue;

		if(area1 > area2){
			swap(area1,area2);
			swap(deg1,deg2);
		}

		Info info;
		info.right = deg1;

		if(area1 == 1){

			switch(area2){
			case 1:
			case 2:
				info.left = deg2;
				break;
			case 3:
				P = getCrossPoints(circle[i],line);

				if(P[0].y > 0 && P[1].y > 0){

					info.left = 180;

				}else{

					info.left = 0;
				}

				break;
			case 4:
				info.left = 0;
				break;
			}

		}else{ //area1 == 2

			switch(area2){
			case 2:
				info.left = deg2;
				break;
			case 3:
				info.left = 180;
				break;
			case 4:
				P = getCrossPoints(circle[i],line);

				if(P[0].y > 0 && P[1].y > 0){

					info.left = 0;

				}else{

					info.left = 180;
				}
				break;
			}
		}

		if(info.right > info.left){

			swap(info.left,info.right);
		}
		work.push_back(info);
	}

	bool FLG;
	//他でカバーできる接線のペアは除く
	for(int i = 0; i < work.size(); i++){
		FLG = false;
		for(int k = i+1; k < work.size(); k++){
			if(k == i)continue;

			if(work[k].left >= work[i].left && work[k].right <= work[i].right){

				FLG = true;
				break;
			}
		}
		if(!FLG){

			V.push_back(work[i]);
		}
	}

	sort(V.begin(),V.end()); //leftの降順

	for(int i = 0; i < V.size(); i++){
		most_L[i] = -1;
		for(int k = 0; k < i; k++){
			if(V[k].right > V[i].left+EPS)continue;

			most_L[i] = k;
			break;
		}
	}

	for(int i = 0; i <= K; i++){
		for(int k = 0; k <= V.size(); k++){
			dp1[i][k] = 0;
			dp2[i][k] = 0;
		}
	}

	double maximum = 0;

	for(int i = 1; i <= K; i++){ //使用個数
		for(int k = 1; k <= V.size(); k++){ //最後のindex(本来のindex+1)
			if(most_L[k-1] == -1){

				dp1[i][k] = dp2[i-1][k-1]+V[k-1].left-V[k-1].right;

			}else{ //重なりを持つ区間あり

				dp1[i][k] = max(dp1[i-1][most_L[k-1]+1]+V[most_L[k-1]].right-V[k-1].right,
						dp2[i-1][most_L[k-1]]+V[k-1].left-V[k-1].right);
			}
			dp2[i][k] = max(dp1[i][k],dp2[i][k-1]);

			maximum = max(maximum,dp2[i][k]);
		}
	}

	printf("%.10lf\n",maximum/180.0);

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 39064
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 1505

struct Point{
    Point(double arg_x,double arg_y){
        x = arg_x;
        y = arg_y;
    }

    Point(){
        x = y = 0.0;
    }

    Point operator + (Point p){ return Point(x+p.x,y+p.y); }
    Point operator - (Point p){ return Point(x-p.x,y-p.y);}
    Point operator * (double a){ return Point(a*x,a*y); }
    Point operator / (double a){ return Point(x/a,y/a); }

    double abs(){ return sqrt(norm()); }
    double norm(){ return x*x + y*y; }

    bool operator<(const Point &p) const{
        return x != p.x? x < p.x: y < p.y;
    }

    bool operator == (const Point &p) const{
        return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
    }

    double x,y;
};

typedef Point Vector;

struct Sphere{
    Point center;
    double r;
};

typedef Sphere Circle;

struct Line{
public:
    Point p[2];
    Line(Point p1,Point p2){
        p[0] = p1;
        p[1] = p2;
    }
    Line(){

    }
};

struct Info{
	bool operator<(const struct Info &arg) const{

		return left > arg.left;
	}
	double left,right;
};

int N,K;
int most_L[SIZE];
vector<Info> work,V;
double dp1[SIZE][SIZE],dp2[SIZE][SIZE];
Circle circle[SIZE];


double NUM = 10000;

double norm(Vector a){
    return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
    return sqrt(norm(a));
}

double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

int main(){

	Point base = Point(0,0);

	scanf("%d %d",&N,&K);

	for(int i = 0; i < N; i++){

		scanf("%lf %lf %lf",&circle[i].center.x,&circle[i].center.y,&circle[i].r);
		if(calc_dist(base,circle[i].center) < circle[i].r){

			printf("1.0\n");
			return 0;
		}
	}

	for(int i = 0; i < N; i++){

		double theta1 = atan2(circle[i].center.y,circle[i].center.x);
		double theta2 = asin(circle[i].r/abs(circle[i].center));

		Info info;
		info.right = theta1-theta2;
		info.left = theta1+theta2;

		if(info.right < -(M_PI+EPS)){

			info.left += 2*M_PI;
			info.right += 2*M_PI;
		}

		info.right = max(info.right,0.0);
		info.left = min(info.left,M_PI);

		if(info.right+EPS > info.left){

			continue;
		}

		work.push_back(info);
	}

	bool FLG;
	//他でカバーできる接線のペアは除く
	for(int i = 0; i < work.size(); i++){
		FLG = false;
		for(int k = i+1; k < work.size(); k++){
			if(k == i)continue;

			if(work[k].left >= work[i].left && work[k].right <= work[i].right){

				FLG = true;
				break;
			}
		}
		if(!FLG){

			V.push_back(work[i]);
		}
	}

	sort(V.begin(),V.end()); //leftの降順

	for(int i = 0; i < V.size(); i++){
		most_L[i] = -1;
		for(int k = 0; k < i; k++){
			if(V[k].right > V[i].left+EPS)continue;

			most_L[i] = k;
			break;
		}
	}

	for(int i = 0; i <= K; i++){
		for(int k = 0; k <= V.size(); k++){
			dp1[i][k] = 0;
			dp2[i][k] = 0;
		}
	}

	double maximum = 0;

	for(int i = 1; i <= K; i++){ //使用個数
		for(int k = 1; k <= V.size(); k++){ //最後のindex(本来のindex+1)
			if(most_L[k-1] == -1){

				dp1[i][k] = dp2[i-1][k-1]+V[k-1].left-V[k-1].right;

			}else{ //重なりを持つ区間あり

				dp1[i][k] = max(dp1[i-1][most_L[k-1]+1]+V[most_L[k-1]].right-V[k-1].right,
						dp2[i-1][most_L[k-1]]+V[k-1].left-V[k-1].right);
			}
			dp2[i][k] = max(dp1[i][k],dp2[i][k-1]);

			maximum = max(maximum,dp2[i][k]);
		}
	}

	printf("%.10lf\n",maximum/M_PI);

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 39032
final_rank: 8

code_snippet: #pragma GCC optimize ("O3")

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <set>
#include <algorithm>
#include <numeric>
#include <list>
using namespace std;

using QWORD  = uint64_t;
using SQWORD = int64_t;
using DWORD  = uint32_t;
using SDWORD = int32_t;
using WORD   = uint16_t;
using SWORD  = int16_t;
using BYTE   = uint8_t;
using SBYTE  = int8_t;
using DOUBLE = double;
using FLOAT  = float;

#define MIN_SDWORD (-2147483648)
#define MAX_SDWORD (2147483647)
#define MIN_SBYTE (-128)
#define MAX_SBYTE (127)

#define MIN_SQWORD (0x8000000000000000)
#define MAX_SQWORD (0x7FFFFFFFFFFFFFFF)

#define MAX_QWORD  (0xFFFFFFFFFFFFFFFF)
#define MAX_DWORD  (0xFFFFFFFF)
#define MAX_WORD   (0xFFFF)
#define MAX_BYTE   (0xFF)

#define MAX_DOUBLE      (1.0e+308)
#define DOUBLE_EPS      (1.0e-12)
#define MIN_DOUBLE_N    (-1.0e+308)

#define ArrayLength(a)  (sizeof(a) / sizeof(a[0]))

static inline DOUBLE MAX(DOUBLE a, DOUBLE b) { return a > b ? a : b; }
static inline QWORD MAX(QWORD a, QWORD b) { return a > b ? a : b; }
static inline DWORD MAX(DWORD a, DWORD b) { return a > b ? a : b; }
static inline SDWORD MAX(SDWORD a, SDWORD b) { return a > b ? a : b; }
static inline DOUBLE MIN(DOUBLE a, DOUBLE b) { return a < b ? a : b; }
static inline QWORD MIN(QWORD a, QWORD b) { return a < b ? a : b; }
static inline DWORD MIN(DWORD a, DWORD b) { return a < b ? a : b; }
static inline SDWORD MIN(SDWORD a, SDWORD b) { return a < b ? a : b; }
static inline DOUBLE ABS(DOUBLE a) { return 0 < a ? a : -a; };

#define BYTE_BITS   (8)
#define WORD_BITS   (16)
#define DWORD_BITS  (32)
#define QWORD_BITS  (64)

#define ANS_MOD (1000000007)

static const DOUBLE d_PI = 3.14159265358979323846;
//static const DOUBLE d_PI = M_PI;


static inline bool DoubleIsEqual(DOUBLE a, DOUBLE b) {
    return ABS(a-b) < DOUBLE_EPS;
}

static inline void inputStringSpSeparated(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c) || (' ' == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}

static inline void inputString(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}


static inline SQWORD inputSQWORD(void)
{
    SQWORD sqNumber = 0;
    SQWORD sqMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                sqMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            sqNumber *= 10LL;
            sqNumber += (SQWORD)(c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return sqNumber * sqMultiplier;
            }
        }
    }
}


static inline SDWORD inputSDWORD(void)
{
    SDWORD lNumber = 0;
    SDWORD lMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                lMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            lNumber *= 10;
            lNumber += (c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return lNumber * lMultiplier;
            }
        }
    }
}

static inline DOUBLE inputFP(void)
{
    DOUBLE dInt = 0.0;
    DOUBLE dFrac = 0.0;
    DOUBLE dMultiplier = 1.0;
    DWORD dwFpCnt = 0;
    DOUBLE *pdCur = &dInt;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                dMultiplier = -1;
            }
        }
        if ('.' == c) {
            pdCur = &dFrac;
        } else if (('0' <= c) && (c <= '9')) {
            (*pdCur) *= 10;
            (*pdCur) += (DOUBLE)(c - '0');
            bRead = true;
            if (pdCur == &dFrac) {
                dwFpCnt++;
            }
        } else {
            if (bRead) {
                return dMultiplier * (dInt + dFrac / (pow((DOUBLE)10.0 , (DOUBLE)dwFpCnt)));
            }
        }
    }
}

/*----------------------------------------------*/
/**
 *  mod による操作ライブラリ
 */
#define ANS_MOD (1000000007)

class MODINT {
    static SQWORD MOD;
    SQWORD m_x;

public:
    MODINT(SQWORD val) {
        m_x = (val % MOD + MOD) % MOD;
    };
    MODINT() {
        m_x = 0;
    }
    static void Init(SQWORD sqMod) {
        MOD = sqMod;
    }

	MODINT& operator+= (const MODINT a)
    {
        m_x = (m_x + a.m_x) % MOD; 
        return *this;
    };
	MODINT& operator-= (const MODINT a)
    { 
        m_x = (m_x - a.m_x + MOD) % MOD; 
        return *this;
    };
	MODINT& operator*= (const MODINT a)
    {
        m_x = (m_x * a.m_x) % MOD;
        return *this;
    };
    MODINT pow(SQWORD t) const {
        if (!t) return 1;
        MODINT a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }
	MODINT operator+ (const MODINT a) const {
		MODINT res(*this);
		return (res += a);
	}
	MODINT operator- (const MODINT a) const {
		MODINT res(*this);
		return (res -= a);
	}
	MODINT operator* (const MODINT a) const {
		MODINT res(*this);
		return (res *= a);
	}
	MODINT operator/ (const MODINT a) const {
		MODINT res(*this);
		return (res /= a);
	}

    /* 逆元 */
    MODINT inv() const {
        return pow(MOD-2);
    }

    /* 除算 */
    MODINT& operator/=(const MODINT a) {
        return (*this) *= a.inv();
    } 

    /* 整数版 */
	MODINT& operator+= (const SQWORD a) {*this += MODINT(a); return *this;};
	MODINT& operator-= (const SQWORD a) {*this -= MODINT(a); return *this;};
	MODINT& operator*= (const SQWORD a) {*this *= MODINT(a); return *this;};
	MODINT& operator/= (const SQWORD a) {*this /= MODINT(a); return *this;};

    SQWORD getVal() { return m_x; };
};
SQWORD MODINT::MOD = ANS_MOD;


/*----------------------------------------------*/

#define EPS 1e-10
DOUBLE double_add(DOUBLE a, DOUBLE b) {
    if (ABS(a + b) < EPS * (ABS(a) + ABS(b))) {
        return 0;
    }
    return a+b;
}

struct VECTOR_2D {
    DOUBLE dX;
    DOUBLE dY;
    VECTOR_2D(DOUBLE x, DOUBLE y) : dX(x), dY(y) {};
    VECTOR_2D() : dX(0), dY(0) {};

    /* 加算 */
	VECTOR_2D& operator+= (const VECTOR_2D a)
    { 
        dX = dX + a.dX;
        dY = dY + a.dY;
        return *this;
    };
    const VECTOR_2D operator+ (const VECTOR_2D a) const {
		return VECTOR_2D(dX + a.dX, dY + a.dY); 
    };

    /* 減算 */
	VECTOR_2D& operator-= (const VECTOR_2D a)
    { 
        dX = dX - a.dX;
        dY = dY - a.dY;
        return *this;
    };
    const VECTOR_2D operator- (const VECTOR_2D a) const {
		return VECTOR_2D(dX - a.dX, dY - a.dY);
    };

    /* 定数倍 */
	VECTOR_2D& operator*= (const DOUBLE a)
    { 
        dX = dX * a;
        dY = dY * a;
        return *this;
    };
    const VECTOR_2D operator* (const DOUBLE a) const {
		return VECTOR_2D(dX * a, dY * a); 
    };

    /* 比較 */
    bool operator< (const VECTOR_2D &a) {
        if (dX == a.dX) {
            return (dY < a.dY);
        }
        return dX < a.dX;
    }

    DOUBLE norm(void) const {
        return (dX * dX + dY * dY);
    }

    DOUBLE dist(void) const {
        return sqrtl(norm());
    }

    DOUBLE angle(void) const {
        return atan2(dY, dX);
    }

    DOUBLE dotproduct(const VECTOR_2D a) const {
        return double_add(dX * a.dX, dY * a.dY);
    }

    DOUBLE crossproduct(const VECTOR_2D a) const {
        return double_add(dX * a.dY, -dY * a.dX);
    }
};



/*----------------------------------------------*/

struct BALL_ST {
    DOUBLE dBegin;
    DOUBLE dEnd;

    BALL_ST (DOUBLE b, DOUBLE e) : dBegin(b), dEnd(e) {};
}; 

bool cmpBegin (const BALL_ST &a, const BALL_ST &b) {
    return a.dBegin < b.dBegin;
}

bool cmpEnd (const BALL_ST &a, const BALL_ST &b) {
    return a.dEnd < b.dEnd;
}

/**
 *  角度の扱い 
 */
static inline DOUBLE normalizeAngle(DOUBLE dAngle)
{
    DOUBLE dRet = dAngle;
    while (dRet < 0.0) {
        dRet += (2.0 * d_PI);
    }

    if (DoubleIsEqual(2.0 * d_PI, dAngle)) {
        dRet = 0.0;
    } else {
        while ((2.0 * d_PI) <= dAngle) {
            dRet -= (2.0 * d_PI);
        }
    }

    return dRet;
}

#define MAX_N (1500)
int main(void)
{
    SQWORD sqN = inputSQWORD();
    SQWORD sqK = inputSQWORD();

    vector<BALL_ST> vecBalls;
    for (SQWORD sqIdx = 0; sqIdx < sqN; sqIdx++) {
        SQWORD sqX = inputSQWORD();
        SQWORD sqY = inputSQWORD();
        SQWORD sqR = inputSQWORD();

        VECTOR_2D stVec((DOUBLE)sqX, (DOUBLE)sqY);
        DOUBLE dAngle = stVec.angle();
        DOUBLE dDist  = stVec.dist();
        DOUBLE dRange = asin((DOUBLE)sqR / dDist);

        DOUBLE dTheta1 = dAngle - dRange;
        DOUBLE dTheta2 = dAngle + dRange;
    
        dTheta1 = normalizeAngle(dTheta1);
        dTheta2 = normalizeAngle(dTheta2);

        DOUBLE dBegin, dEnd;

        if (d_PI <= dTheta1 && d_PI <= dTheta2) {
            dBegin = 0.0;
            dEnd = 0.0;
        } else if (d_PI <= dTheta1) {
            dBegin = 0.0;
            dEnd = dTheta2;
        } else if (d_PI <= dTheta2){
            dBegin = dTheta1;
            dEnd = d_PI;
        } else {
            dBegin = dTheta1;
            dEnd = dTheta2;
        }
//        printf("%f %f\n", dBegin, dEnd);
        vecBalls.emplace_back(dBegin, dEnd);
    }
    sort(vecBalls.begin(), vecBalls.end(), cmpBegin);
	/* 含まれてしまうものは除く */
	int sqSz = 0;
	for (int i = 0; i < sqN; i++) {
		bool isIinJ = false;
		for (int j = 1; j <= sqN; j++) {
			if (i == j) continue;
			if ((vecBalls[j].dBegin < vecBalls[i].dBegin) && (vecBalls[i].dEnd < vecBalls[j].dEnd)) {
				isIinJ = true;
			}
		}
		if (!isIinJ) {
			vecBalls[sqSz++] = vecBalls[i];
		}
	}
//    for (auto b: vecBalls) {
//        printf(":%f %f\n", b.dBegin, b.dEnd);
//    }

    /**
     *  dp[j][k]    左端がk番目のボールで、
     *              j個を使っているときの最大の角度
     *  dp[j][k] = max(dp[j-1][0] + angle, dp[j-1][1] + angle, dp[j-1][2] + angle ,,,, dp[j-1][k-1] + angle)
     * 
     */
    static DOUBLE s_aadDpTbl[MAX_N + 1][MAX_N + 1];
    for (SQWORD sqIdxJ = 0; sqIdxJ <= sqK; sqIdxJ++) {
        for (SQWORD sqIdxK = 0; sqIdxK <= sqSz; sqIdxK++) {
            s_aadDpTbl[sqIdxJ][sqIdxK] = 0.0;
        }
    }

	double dAns = 0;

	for (int i = 1; i <= sqK; i++) {
		for (int j = 0; j < sqSz; j++) {
			double best = 0;
			int k = 0;

			while (vecBalls[k].dEnd < vecBalls[j].dBegin) {
				best = max(best, s_aadDpTbl[i-1][k]);
				k++;
			}

//            printf("--%d %f %f\n", j, vecBalls[j].dEnd, vecBalls[j].dBegin);
			
			s_aadDpTbl[i][j] = max(s_aadDpTbl[i][j], best + vecBalls[j].dEnd - vecBalls[j].dBegin);
			s_aadDpTbl[i][j] = max(s_aadDpTbl[i][j], s_aadDpTbl[i-1][k] + vecBalls[j].dEnd - vecBalls[k].dEnd);
			dAns = max(dAns, s_aadDpTbl[i][j]);
//            printf("%f ", s_aadDpTbl[i][j]);
		}
//        printf("\n");
	}

#if 0
    DOUBLE dAns = 0.0;
    for (SQWORD sqIdxJ = 0; sqIdxJ < sqK; sqIdxJ++) {
        for (SQWORD sqIdxK = 0; sqIdxK < sz; sqIdxK++) {
            DOUBLE dPrevEnd = vecBalls[sqIdxK].dEnd;
            for (SQWORD sqNextBallIdx = sqIdxK + 1; sqNextBallIdx <= sz; sqNextBallIdx++) {
                BALL_ST stBall = vecBalls[sqNextBallIdx];
                DOUBLE dAddAngle = 0;
                if (dPrevEnd <= stBall.dBegin) {
                    /* 重なってない */
                    dAddAngle = stBall.dEnd - stBall.dBegin;
//                printf("> [%lld %lld %lld] %llf ", sqIdxJ, sqIdxK, sqNextBallIdx, dAddAngle / d_PI);
                    s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx] 
                        = MAX(s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx], s_aadDpTbl[sqIdxJ][sqIdxK] + dAddAngle);
                } else {
                    /* 重なってる */
                     dAddAngle = stBall.dEnd - dPrevEnd;
                     s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx] 
                         = MAX(s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx], s_aadDpTbl[sqIdxJ][sqIdxK] + dAddAngle);
//                printf("< [%lld %lld %lld] %llf ", sqIdxJ, sqIdxK, sqNextBallIdx, dAddAngle / d_PI);
                }

                dAns = max(s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx], dAns);
            }
        }
//        printf("\n");
    }
#endif

    printf("%0.11f\n", dAns / d_PI);

    return 0;
}
accuracy: 1
time_ms: 330
memory_kb: 21172
final_rank: 11

code_snippet: #define _USE_MATH_DEFINES
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
#include <numeric>
#include <tuple>
#include <iomanip>
#include <assert.h>

#define sqr(x) std::pow(x, 2.0)
#define INF 1e10
#define EPS 1e-10
#define REP(i, n) for (int i = 0; i < n; i++)
#define POS_OR_INF(x) (x > 0 ? x : INF)

using namespace std;

using ld = long double;

struct Point {
	Point() = default;
	Point(ld x, ld y) : x(x), y(y) {}
	Point(const Point& s, const Point& e) : x(e.x - s.x), y(e.y - s.y) {}

	Point normalized(void) const {
		return Point(x / norm(), y / norm());
	}

	ld norm(void) const {
		return sqrt(x * x + y * y);
	}

	Point flipped(void) const {
		return Point(-x, -y);
	}

	Point normal_vector(bool normalize = false) const {
		auto vec = Point(-y, x);
		return normalize ? vec.normalized() : vec;
	}

	ld x, y;
};

using Vector = Point;

inline Vector points2vec(const Point& s, const Point& e) {
	return Vector(e.x - s.x, e.y - s.y);
}

inline ld distance(const Point& s, const Point& e) {
	return points2vec(s, e).norm();
}

inline ld distance_square(const Point& s, const Point& e) {
	return pow(points2vec(s, e).norm(), 2.0);
}

inline Vector operator * (const Vector& l, ld r) {
	return Vector(l.x * r, l.y * r);
}

inline Vector operator * (ld l, const Vector& r) {
	return r * l;
}

inline Vector operator / (const Vector& l, ld r) {
	return Vector(l.x / r, l.y / r);
}

inline Point operator + (const Point& l, const Point& r) {
	return Point(l.x + r.x, l.y + r.y);
}

inline Point operator - (const Point& l, const Point& r) {
	return Point(l.x - r.x, l.y - r.y);
}

inline istream& operator >> (istream& is, Point& p) {
	return is >> p.x >> p.y;
}

int main(int argc, char** argv) {
	int N, K;

	cin >> N >> K;
	cout << fixed << setprecision(20);

	vector<pair<double, double>> a(N), b;

	for (int i = 0; i < N; i++) {
		Point p;
		double r;
		cin >> p >> r;

		double theta = asin(r/p.norm());
		double rad = atan2(p.y, p.x);

		if (rad < -M_PI / 2) rad += 2 * M_PI;

		a[i].first = min(M_PI, max(0.0, rad - theta));
		a[i].second = min(M_PI, max(0.0, rad + theta));
	}

	for (int i = 0; i < N; i++) {
		bool included = false;
		for (int j = 0; j < N; j++) {
			if (a[i].first > a[j].first && a[i].second < a[j].second)
				included = true;
		}
		if (!included) {
			b.push_back(a[i]);
		}
	}

	sort(b.begin(), b.end());

	int M = b.size();

	vector<vector<double>> dp(K + 1, vector<double>(M + 1, 0));
	double ans = 0;

	for (int i = 1; i <= K; i++) {
		for (int j = 0; j < M; j++) {
			double best = 0;
			int k = 0;

			while (b[k].second < b[j].first) {
				best = max(best, dp[i-1][k]);
				k++;
			}
			
			dp[i][j] = max(dp[i][j], best + b[j].second - b[j].first);
			dp[i][j] = max(dp[i][j], dp[i-1][k] + b[j].second - b[k].second);
			ans = max(ans, dp[i][j]);
		}
	}

	cout << ans / M_PI;
}
accuracy: 1
time_ms: 340
memory_kb: 20612
final_rank: 12

code_snippet: #pragma GCC optimize ("O3")

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <set>
#include <algorithm>
#include <numeric>
#include <list>
using namespace std;

using QWORD  = uint64_t;
using SQWORD = int64_t;
using DWORD  = uint32_t;
using SDWORD = int32_t;
using WORD   = uint16_t;
using SWORD  = int16_t;
using BYTE   = uint8_t;
using SBYTE  = int8_t;
using DOUBLE = double;
using FLOAT  = float;

#define MIN_SDWORD (-2147483648)
#define MAX_SDWORD (2147483647)
#define MIN_SBYTE (-128)
#define MAX_SBYTE (127)

#define MIN_SQWORD (0x8000000000000000)
#define MAX_SQWORD (0x7FFFFFFFFFFFFFFF)

#define MAX_QWORD  (0xFFFFFFFFFFFFFFFF)
#define MAX_DWORD  (0xFFFFFFFF)
#define MAX_WORD   (0xFFFF)
#define MAX_BYTE   (0xFF)

#define MAX_DOUBLE      (1.0e+308)
#define DOUBLE_EPS      (1.0e-12)
#define MIN_DOUBLE_N    (-1.0e+308)

#define ArrayLength(a)  (sizeof(a) / sizeof(a[0]))

static inline DOUBLE MAX(DOUBLE a, DOUBLE b) { return a > b ? a : b; }
static inline QWORD MAX(QWORD a, QWORD b) { return a > b ? a : b; }
static inline DWORD MAX(DWORD a, DWORD b) { return a > b ? a : b; }
static inline SDWORD MAX(SDWORD a, SDWORD b) { return a > b ? a : b; }
static inline DOUBLE MIN(DOUBLE a, DOUBLE b) { return a < b ? a : b; }
static inline QWORD MIN(QWORD a, QWORD b) { return a < b ? a : b; }
static inline DWORD MIN(DWORD a, DWORD b) { return a < b ? a : b; }
static inline SDWORD MIN(SDWORD a, SDWORD b) { return a < b ? a : b; }
static inline DOUBLE ABS(DOUBLE a) { return 0 < a ? a : -a; };

#define BYTE_BITS   (8)
#define WORD_BITS   (16)
#define DWORD_BITS  (32)
#define QWORD_BITS  (64)

#define ANS_MOD (1000000007)

static const DOUBLE d_PI = 3.14159265358979323846;

static inline bool DoubleIsEqual(DOUBLE a, DOUBLE b) {
    return ABS(a-b) < DOUBLE_EPS;
}

static inline void inputStringSpSeparated(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c) || (' ' == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}

static inline void inputString(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}


static inline SQWORD inputSQWORD(void)
{
    SQWORD sqNumber = 0;
    SQWORD sqMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                sqMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            sqNumber *= 10LL;
            sqNumber += (SQWORD)(c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return sqNumber * sqMultiplier;
            }
        }
    }
}


static inline SDWORD inputSDWORD(void)
{
    SDWORD lNumber = 0;
    SDWORD lMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                lMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            lNumber *= 10;
            lNumber += (c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return lNumber * lMultiplier;
            }
        }
    }
}

static inline DOUBLE inputFP(void)
{
    DOUBLE dInt = 0.0;
    DOUBLE dFrac = 0.0;
    DOUBLE dMultiplier = 1.0;
    DWORD dwFpCnt = 0;
    DOUBLE *pdCur = &dInt;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                dMultiplier = -1;
            }
        }
        if ('.' == c) {
            pdCur = &dFrac;
        } else if (('0' <= c) && (c <= '9')) {
            (*pdCur) *= 10;
            (*pdCur) += (DOUBLE)(c - '0');
            bRead = true;
            if (pdCur == &dFrac) {
                dwFpCnt++;
            }
        } else {
            if (bRead) {
                return dMultiplier * (dInt + dFrac / (pow((DOUBLE)10.0 , (DOUBLE)dwFpCnt)));
            }
        }
    }
}

/*----------------------------------------------*/
/**
 *  mod による操作ライブラリ
 */
#define ANS_MOD (1000000007)

class MODINT {
    static SQWORD MOD;
    SQWORD m_x;

public:
    MODINT(SQWORD val) {
        m_x = (val % MOD + MOD) % MOD;
    };
    MODINT() {
        m_x = 0;
    }
    static void Init(SQWORD sqMod) {
        MOD = sqMod;
    }

	MODINT& operator+= (const MODINT a)
    {
        m_x = (m_x + a.m_x) % MOD; 
        return *this;
    };
	MODINT& operator-= (const MODINT a)
    { 
        m_x = (m_x - a.m_x + MOD) % MOD; 
        return *this;
    };
	MODINT& operator*= (const MODINT a)
    {
        m_x = (m_x * a.m_x) % MOD;
        return *this;
    };
    MODINT pow(SQWORD t) const {
        if (!t) return 1;
        MODINT a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }
	MODINT operator+ (const MODINT a) const {
		MODINT res(*this);
		return (res += a);
	}
	MODINT operator- (const MODINT a) const {
		MODINT res(*this);
		return (res -= a);
	}
	MODINT operator* (const MODINT a) const {
		MODINT res(*this);
		return (res *= a);
	}
	MODINT operator/ (const MODINT a) const {
		MODINT res(*this);
		return (res /= a);
	}

    /* 逆元 */
    MODINT inv() const {
        return pow(MOD-2);
    }

    /* 除算 */
    MODINT& operator/=(const MODINT a) {
        return (*this) *= a.inv();
    } 

    /* 整数版 */
	MODINT& operator+= (const SQWORD a) {*this += MODINT(a); return *this;};
	MODINT& operator-= (const SQWORD a) {*this -= MODINT(a); return *this;};
	MODINT& operator*= (const SQWORD a) {*this *= MODINT(a); return *this;};
	MODINT& operator/= (const SQWORD a) {*this /= MODINT(a); return *this;};

    SQWORD getVal() { return m_x; };
};
SQWORD MODINT::MOD = ANS_MOD;


/*----------------------------------------------*/

#define EPS 1e-10
DOUBLE double_add(DOUBLE a, DOUBLE b) {
    if (ABS(a + b) < EPS * (ABS(a) + ABS(b))) {
        return 0;
    }
    return a+b;
}

struct VECTOR_2D {
    DOUBLE dX;
    DOUBLE dY;
    VECTOR_2D(DOUBLE x, DOUBLE y) : dX(x), dY(y) {};
    VECTOR_2D() : dX(0), dY(0) {};

    /* 加算 */
	VECTOR_2D& operator+= (const VECTOR_2D a)
    { 
        dX = dX + a.dX;
        dY = dY + a.dY;
        return *this;
    };
    const VECTOR_2D operator+ (const VECTOR_2D a) const {
		return VECTOR_2D(dX + a.dX, dY + a.dY); 
    };

    /* 減算 */
	VECTOR_2D& operator-= (const VECTOR_2D a)
    { 
        dX = dX - a.dX;
        dY = dY - a.dY;
        return *this;
    };
    const VECTOR_2D operator- (const VECTOR_2D a) const {
		return VECTOR_2D(dX - a.dX, dY - a.dY);
    };

    /* 定数倍 */
	VECTOR_2D& operator*= (const DOUBLE a)
    { 
        dX = dX * a;
        dY = dY * a;
        return *this;
    };
    const VECTOR_2D operator* (const DOUBLE a) const {
		return VECTOR_2D(dX * a, dY * a); 
    };

    /* 比較 */
    bool operator< (const VECTOR_2D &a) {
        if (dX == a.dX) {
            return (dY < a.dY);
        }
        return dX < a.dX;
    }

    DOUBLE norm(void) const {
        return (dX * dX + dY * dY);
    }

    DOUBLE dist(void) const {
        return sqrtl(norm());
    }

    DOUBLE angle(void) const {
        return atan2(dY, dX);
    }

    DOUBLE dotproduct(const VECTOR_2D a) const {
        return double_add(dX * a.dX, dY * a.dY);
    }

    DOUBLE crossproduct(const VECTOR_2D a) const {
        return double_add(dX * a.dY, -dY * a.dX);
    }
};



/*----------------------------------------------*/

struct BALL_ST {
    DOUBLE dBegin;
    DOUBLE dEnd;

    BALL_ST (DOUBLE b, DOUBLE e) : dBegin(b), dEnd(e) {};
}; 

bool cmpBegin (const BALL_ST &a, const BALL_ST &b) {
    return a.dBegin < b.dBegin;
}

bool cmpEnd (const BALL_ST &a, const BALL_ST &b) {
    return a.dEnd < b.dEnd;
}

/**
 *  角度の扱い 
 */
static inline DOUBLE normalizeAngle(DOUBLE dAngle)
{
    DOUBLE dRet = dAngle;
    while (dRet < 0.0) {
        dRet += (2.0 * d_PI);
    }

    if (DoubleIsEqual(2.0 * d_PI, dAngle)) {
        dRet = 0.0;
    } else {
        while ((2.0 * d_PI) <= dAngle) {
            dRet -= (2.0 * d_PI);
        }
    }

    return dRet;
}

#define MAX_N (1500)
int main(void)
{
    SQWORD sqN = inputSQWORD();
    SQWORD sqK = inputSQWORD();

    vector<BALL_ST> vecBalls;
    vecBalls.emplace_back(0, 0);    /* dp用にインデックスを1はじまりにするためのダミー */
    for (SQWORD sqIdx = 0; sqIdx < sqN; sqIdx++) {
        SQWORD sqX = inputSQWORD();
        SQWORD sqY = inputSQWORD();
        SQWORD sqR = inputSQWORD();

        VECTOR_2D stVec((DOUBLE)sqX, (DOUBLE)sqY);
        DOUBLE dAngle = stVec.angle();
        DOUBLE dDist  = stVec.dist();
        DOUBLE dRange = asin((DOUBLE)sqR / dDist);

        DOUBLE dTheta1 = dAngle - dRange;
        DOUBLE dTheta2 = dAngle + dRange;
    
        dTheta1 = normalizeAngle(dTheta1);
        dTheta2 = normalizeAngle(dTheta2);

        DOUBLE dBegin, dEnd;

        if (d_PI <= dTheta1 && d_PI <= dTheta2) {
            dBegin = 0.0;
            dEnd = 0.0;
        } else if (d_PI <= dTheta1) {
            dBegin = 0.0;
            dEnd = dTheta2;
        } else if (d_PI <= dTheta2){
            dBegin = dTheta1;
            dEnd = d_PI;
        } else {
            dBegin = dTheta1;
            dEnd = dTheta2;
        }
        vecBalls.emplace_back(dBegin, dEnd);
    }
    sort(vecBalls.begin(), vecBalls.end(), cmpBegin);

    /**
     *  dp[j][k]    左端がk番目のボールで、
     *              j個を使っているときの最大の角度
     *  dp[j][k] = max(dp[j-1][0] + angle, dp[j-1][1] + angle, dp[j-1][2] + angle ,,,, dp[j-1][k-1] + angle)
     * 
     */
    static DOUBLE s_aadDpTbl[MAX_N + 1][MAX_N + 1];
    for (SQWORD sqIdxJ = 0; sqIdxJ <= sqN; sqIdxJ++) {
        for (SQWORD sqIdxK = 0; sqIdxK <= sqN; sqIdxK++) {
            s_aadDpTbl[sqIdxJ][sqIdxK] = 0.0;
        }
    }
    for (SQWORD sqIdxJ = 0; sqIdxJ < sqN; sqIdxJ++) {
        for (SQWORD sqIdxK = sqIdxJ; sqIdxK < sqN; sqIdxK++) {
            DOUBLE dPrevEnd;
            if (0.0 == s_aadDpTbl[sqIdxJ][sqIdxK]) {
                dPrevEnd = 0.0;
            } else {
                dPrevEnd = vecBalls[sqIdxK].dEnd;
            } 
            for (SQWORD sqNextBallIdx = sqIdxK + 1; sqNextBallIdx <= sqN; sqNextBallIdx++) {
                BALL_ST stBall = vecBalls[sqNextBallIdx];
                DOUBLE dAddAngle = 0;
                if (dPrevEnd < stBall.dBegin) {
                    dAddAngle = stBall.dEnd - stBall.dBegin;
//                printf("> [%lld %lld %lld] %llf ", sqIdxJ, sqIdxK, sqNextBallIdx, dAddAngle / d_PI);
                    s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx] 
                        = MAX(s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx], s_aadDpTbl[sqIdxJ][sqIdxK] + dAddAngle);
                } else {
                    if (dPrevEnd < stBall.dEnd) {
                        dAddAngle = stBall.dEnd - dPrevEnd;
                        s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx] 
                            = MAX(s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx], s_aadDpTbl[sqIdxJ][sqIdxK] + dAddAngle);
                    }
//                printf("< [%lld %lld %lld] %llf ", sqIdxJ, sqIdxK, sqNextBallIdx, dAddAngle / d_PI);
                }

            }
        }
//        printf("\n");
    }

    DOUBLE dAns = 0.0;
    for (SQWORD sqIdxJ = 1; sqIdxJ <= sqK; sqIdxJ++) {
        for (SQWORD sqIdxK = sqIdxJ; sqIdxK <= sqN; sqIdxK++) {
//            printf("%llf ", s_aadDpTbl[sqIdxJ][sqIdxK] / d_PI);
            dAns = max(dAns, s_aadDpTbl[sqIdxJ][sqIdxK]);
        }
//        printf("\n");
    }

    printf("%0.11f\n", dAns / d_PI);

    return 0;
}
accuracy: 0.3380281690140845
time_ms: 710
memory_kb: 21144
final_rank: 18

code_snippet: #pragma GCC optimize ("O3")

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <set>
#include <algorithm>
#include <numeric>
#include <list>
using namespace std;

using QWORD  = uint64_t;
using SQWORD = int64_t;
using DWORD  = uint32_t;
using SDWORD = int32_t;
using WORD   = uint16_t;
using SWORD  = int16_t;
using BYTE   = uint8_t;
using SBYTE  = int8_t;
using DOUBLE = double;
using FLOAT  = float;

#define MIN_SDWORD (-2147483648)
#define MAX_SDWORD (2147483647)
#define MIN_SBYTE (-128)
#define MAX_SBYTE (127)

#define MIN_SQWORD (0x8000000000000000)
#define MAX_SQWORD (0x7FFFFFFFFFFFFFFF)

#define MAX_QWORD  (0xFFFFFFFFFFFFFFFF)
#define MAX_DWORD  (0xFFFFFFFF)
#define MAX_WORD   (0xFFFF)
#define MAX_BYTE   (0xFF)

#define MAX_DOUBLE      (1.0e+308)
#define DOUBLE_EPS      (1.0e-12)
#define MIN_DOUBLE_N    (-1.0e+308)

#define ArrayLength(a)  (sizeof(a) / sizeof(a[0]))

static inline DOUBLE MAX(DOUBLE a, DOUBLE b) { return a > b ? a : b; }
static inline QWORD MAX(QWORD a, QWORD b) { return a > b ? a : b; }
static inline DWORD MAX(DWORD a, DWORD b) { return a > b ? a : b; }
static inline SDWORD MAX(SDWORD a, SDWORD b) { return a > b ? a : b; }
static inline DOUBLE MIN(DOUBLE a, DOUBLE b) { return a < b ? a : b; }
static inline QWORD MIN(QWORD a, QWORD b) { return a < b ? a : b; }
static inline DWORD MIN(DWORD a, DWORD b) { return a < b ? a : b; }
static inline SDWORD MIN(SDWORD a, SDWORD b) { return a < b ? a : b; }
static inline DOUBLE ABS(DOUBLE a) { return 0 < a ? a : -a; };

#define BYTE_BITS   (8)
#define WORD_BITS   (16)
#define DWORD_BITS  (32)
#define QWORD_BITS  (64)

#define ANS_MOD (1000000007)

static const DOUBLE d_PI = 3.14159265358979323846;


static inline void inputStringSpSeparated(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c) || (' ' == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}

static inline void inputString(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}


static inline SQWORD inputSQWORD(void)
{
    SQWORD sqNumber = 0;
    SQWORD sqMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                sqMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            sqNumber *= 10LL;
            sqNumber += (SQWORD)(c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return sqNumber * sqMultiplier;
            }
        }
    }
}


static inline SDWORD inputSDWORD(void)
{
    SDWORD lNumber = 0;
    SDWORD lMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                lMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            lNumber *= 10;
            lNumber += (c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return lNumber * lMultiplier;
            }
        }
    }
}

static inline DOUBLE inputFP(void)
{
    DOUBLE dInt = 0.0;
    DOUBLE dFrac = 0.0;
    DOUBLE dMultiplier = 1.0;
    DWORD dwFpCnt = 0;
    DOUBLE *pdCur = &dInt;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                dMultiplier = -1;
            }
        }
        if ('.' == c) {
            pdCur = &dFrac;
        } else if (('0' <= c) && (c <= '9')) {
            (*pdCur) *= 10;
            (*pdCur) += (DOUBLE)(c - '0');
            bRead = true;
            if (pdCur == &dFrac) {
                dwFpCnt++;
            }
        } else {
            if (bRead) {
                return dMultiplier * (dInt + dFrac / (pow((DOUBLE)10.0 , (DOUBLE)dwFpCnt)));
            }
        }
    }
}

/*----------------------------------------------*/
/**
 *  mod による操作ライブラリ
 */
#define ANS_MOD (1000000007)

class MODINT {
    static SQWORD MOD;
    SQWORD m_x;

public:
    MODINT(SQWORD val) {
        m_x = (val % MOD + MOD) % MOD;
    };
    MODINT() {
        m_x = 0;
    }
    static void Init(SQWORD sqMod) {
        MOD = sqMod;
    }

	MODINT& operator+= (const MODINT a)
    {
        m_x = (m_x + a.m_x) % MOD; 
        return *this;
    };
	MODINT& operator-= (const MODINT a)
    { 
        m_x = (m_x - a.m_x + MOD) % MOD; 
        return *this;
    };
	MODINT& operator*= (const MODINT a)
    {
        m_x = (m_x * a.m_x) % MOD;
        return *this;
    };
    MODINT pow(SQWORD t) const {
        if (!t) return 1;
        MODINT a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }
	MODINT operator+ (const MODINT a) const {
		MODINT res(*this);
		return (res += a);
	}
	MODINT operator- (const MODINT a) const {
		MODINT res(*this);
		return (res -= a);
	}
	MODINT operator* (const MODINT a) const {
		MODINT res(*this);
		return (res *= a);
	}
	MODINT operator/ (const MODINT a) const {
		MODINT res(*this);
		return (res /= a);
	}

    /* 逆元 */
    MODINT inv() const {
        return pow(MOD-2);
    }

    /* 除算 */
    MODINT& operator/=(const MODINT a) {
        return (*this) *= a.inv();
    } 

    /* 整数版 */
	MODINT& operator+= (const SQWORD a) {*this += MODINT(a); return *this;};
	MODINT& operator-= (const SQWORD a) {*this -= MODINT(a); return *this;};
	MODINT& operator*= (const SQWORD a) {*this *= MODINT(a); return *this;};
	MODINT& operator/= (const SQWORD a) {*this /= MODINT(a); return *this;};

    SQWORD getVal() { return m_x; };
};
SQWORD MODINT::MOD = ANS_MOD;


/*----------------------------------------------*/

#define EPS 1e-10
DOUBLE double_add(DOUBLE a, DOUBLE b) {
    if (ABS(a + b) < EPS * (ABS(a) + ABS(b))) {
        return 0;
    }
    return a+b;
}

struct VECTOR_2D {
    DOUBLE dX;
    DOUBLE dY;
    VECTOR_2D(DOUBLE x, DOUBLE y) : dX(x), dY(y) {};
    VECTOR_2D() : dX(0), dY(0) {};

    /* 加算 */
	VECTOR_2D& operator+= (const VECTOR_2D a)
    { 
        dX = dX + a.dX;
        dY = dY + a.dY;
        return *this;
    };
    const VECTOR_2D operator+ (const VECTOR_2D a) const {
		return VECTOR_2D(dX + a.dX, dY + a.dY); 
    };

    /* 減算 */
	VECTOR_2D& operator-= (const VECTOR_2D a)
    { 
        dX = dX - a.dX;
        dY = dY - a.dY;
        return *this;
    };
    const VECTOR_2D operator- (const VECTOR_2D a) const {
		return VECTOR_2D(dX - a.dX, dY - a.dY);
    };

    /* 定数倍 */
	VECTOR_2D& operator*= (const DOUBLE a)
    { 
        dX = dX * a;
        dY = dY * a;
        return *this;
    };
    const VECTOR_2D operator* (const DOUBLE a) const {
		return VECTOR_2D(dX * a, dY * a); 
    };

    /* 比較 */
    bool operator< (const VECTOR_2D &a) {
        if (dX == a.dX) {
            return (dY < a.dY);
        }
        return dX < a.dX;
    }

    DOUBLE norm(void) const {
        return (dX * dX + dY * dY);
    }

    DOUBLE dist(void) const {
        return sqrtl(norm());
    }

    DOUBLE angle(void) const {
        return atan2(dY, dX);
    }

    DOUBLE dotproduct(const VECTOR_2D a) const {
        return double_add(dX * a.dX, dY * a.dY);
    }

    DOUBLE crossproduct(const VECTOR_2D a) const {
        return double_add(dX * a.dY, -dY * a.dX);
    }
};



/*----------------------------------------------*/

struct BALL_ST {
    DOUBLE dBegin;
    DOUBLE dEnd;

    BALL_ST (DOUBLE b, DOUBLE e) : dBegin(b), dEnd(e) {};
}; 

bool cmpBegin (const BALL_ST &a, const BALL_ST &b) {
    return a.dBegin < b.dBegin;
}

bool cmpEnd (const BALL_ST &a, const BALL_ST &b) {
    return a.dEnd < b.dEnd;
}

/**
 *  角度の扱い 
 */
static inline DOUBLE normalizeAngle(DOUBLE dAngle)
{
    DOUBLE dRet = dAngle;
    while (dRet < 0.0) {
        dRet += (2.0 * d_PI);
    }

    while ((2.0 * d_PI) < dAngle) {
        dRet -= (2.0 * d_PI);
    }

    return dRet;
}

#define MAX_N (1500)
int main(void)
{
    SQWORD sqN = inputSQWORD();
    SQWORD sqK = inputSQWORD();

    vector<BALL_ST> vecBalls;
    vecBalls.emplace_back(0, 0);    /* dp用にインデックスを1はじまりにするためのダミー */
    for (SQWORD sqIdx = 0; sqIdx < sqN; sqIdx++) {
        SQWORD sqX = inputSQWORD();
        SQWORD sqY = inputSQWORD();
        SQWORD sqR = inputSQWORD();

        VECTOR_2D stVec((DOUBLE)sqX, (DOUBLE)sqY);
        DOUBLE dAngle = normalizeAngle(stVec.angle());
        DOUBLE dDist  = stVec.dist();
        DOUBLE dRange = asin((DOUBLE)sqR / dDist);
    
        DOUBLE dBegin, dEnd;
        if (2 * d_PI <= (dAngle + dRange)) {
            dBegin = 0.0;
            dEnd = dAngle + dRange - (2 * d_PI);
        } else {
            dBegin = MIN(MAX(dAngle - dRange, 0.0), d_PI);
            dEnd   = MIN(MAX(dAngle + dRange, 0.0), d_PI); 
        }



//        printf("%0.10f %0.10f\n", dBegin, dEnd);

        vecBalls.emplace_back(dBegin, dEnd);
    }
    sort(vecBalls.begin(), vecBalls.end(), cmpBegin);

    /**
     *  dp[j][k]    左端がk番目のボールで、
     *              j個を使っているときの最大の角度
     *  dp[j][k] = max(dp[j-1][0] + angle, dp[j-1][1] + angle, dp[j-1][2] + angle ,,,, dp[j-1][k-1] + angle)
     * 
     */
    static DOUBLE s_aadDpTbl[MAX_N + 1][MAX_N + 1];
    for (SQWORD sqIdxJ = 0; sqIdxJ <= sqN; sqIdxJ++) {
        for (SQWORD sqIdxK = 0; sqIdxK <= sqN; sqIdxK++) {
            s_aadDpTbl[sqIdxJ][sqIdxK] = 0;
        }
    }
    for (SQWORD sqIdxJ = 0; sqIdxJ < sqN; sqIdxJ++) {
        for (SQWORD sqIdxK = sqIdxJ; sqIdxK < sqN; sqIdxK++) {
            DOUBLE dPrevEnd = vecBalls[sqIdxK].dEnd;
            for (SQWORD sqNextBallIdx = sqIdxK + 1; sqNextBallIdx <= sqN; sqNextBallIdx++) {
                BALL_ST stBall = vecBalls[sqNextBallIdx];
                DOUBLE dAddAngle = 0;
                if (dPrevEnd < stBall.dBegin) {
                    dAddAngle = stBall.dEnd - stBall.dBegin;
//                printf("> [%lld %lld %lld] %llf ", sqIdxJ, sqIdxK, sqNextBallIdx, dAddAngle / d_PI);
                    s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx] 
                        = max(s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx], s_aadDpTbl[sqIdxJ][sqIdxK] + dAddAngle);
                } else {
                    if (dPrevEnd < stBall.dEnd) {
                        dAddAngle = stBall.dEnd - dPrevEnd;
                        s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx] 
                            = max(s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx], s_aadDpTbl[sqIdxJ][sqIdxK] + dAddAngle);
                    }
//                printf("< [%lld %lld %lld] %llf ", sqIdxJ, sqIdxK, sqNextBallIdx, dAddAngle / d_PI);
                }

            }
        }
//        printf("\n");
    }

    DOUBLE dAns = 0.0;
    for (SQWORD sqIdxJ = 1; sqIdxJ <= sqK; sqIdxJ++) {
        for (SQWORD sqIdxK = sqIdxJ; sqIdxK <= sqN; sqIdxK++) {
//            printf("%llf ", s_aadDpTbl[sqIdxJ][sqIdxK] / d_PI);
            dAns = max(dAns, s_aadDpTbl[sqIdxJ][sqIdxK]);
        }
//        printf("\n");
    }

    printf("%0.11f\n", dAns / d_PI);

    return 0;
}
accuracy: 0.3380281690140845
time_ms: 570
memory_kb: 21292
final_rank: 17

code_snippet: #pragma GCC optimize ("O3")

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <set>
#include <algorithm>
#include <numeric>
#include <list>
using namespace std;

using QWORD  = uint64_t;
using SQWORD = int64_t;
using DWORD  = uint32_t;
using SDWORD = int32_t;
using WORD   = uint16_t;
using SWORD  = int16_t;
using BYTE   = uint8_t;
using SBYTE  = int8_t;
using DOUBLE = double;
using FLOAT  = float;

#define MIN_SDWORD (-2147483648)
#define MAX_SDWORD (2147483647)
#define MIN_SBYTE (-128)
#define MAX_SBYTE (127)

#define MIN_SQWORD (0x8000000000000000)
#define MAX_SQWORD (0x7FFFFFFFFFFFFFFF)

#define MAX_QWORD  (0xFFFFFFFFFFFFFFFF)
#define MAX_DWORD  (0xFFFFFFFF)
#define MAX_WORD   (0xFFFF)
#define MAX_BYTE   (0xFF)

#define MAX_DOUBLE      (1.0e+308)
#define DOUBLE_EPS      (1.0e-12)
#define MIN_DOUBLE_N    (-1.0e+308)

#define ArrayLength(a)  (sizeof(a) / sizeof(a[0]))

static inline DOUBLE MAX(DOUBLE a, DOUBLE b) { return a > b ? a : b; }
static inline QWORD MAX(QWORD a, QWORD b) { return a > b ? a : b; }
static inline DWORD MAX(DWORD a, DWORD b) { return a > b ? a : b; }
static inline SDWORD MAX(SDWORD a, SDWORD b) { return a > b ? a : b; }
static inline DOUBLE MIN(DOUBLE a, DOUBLE b) { return a < b ? a : b; }
static inline QWORD MIN(QWORD a, QWORD b) { return a < b ? a : b; }
static inline DWORD MIN(DWORD a, DWORD b) { return a < b ? a : b; }
static inline SDWORD MIN(SDWORD a, SDWORD b) { return a < b ? a : b; }
static inline DOUBLE ABS(DOUBLE a) { return 0 < a ? a : -a; };

#define BYTE_BITS   (8)
#define WORD_BITS   (16)
#define DWORD_BITS  (32)
#define QWORD_BITS  (64)

#define ANS_MOD (1000000007)

static const DOUBLE d_PI = 3.14159265358979323846;


static inline void inputStringSpSeparated(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c) || (' ' == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}

static inline void inputString(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}


static inline SQWORD inputSQWORD(void)
{
    SQWORD sqNumber = 0;
    SQWORD sqMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                sqMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            sqNumber *= 10LL;
            sqNumber += (SQWORD)(c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return sqNumber * sqMultiplier;
            }
        }
    }
}


static inline SDWORD inputSDWORD(void)
{
    SDWORD lNumber = 0;
    SDWORD lMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                lMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            lNumber *= 10;
            lNumber += (c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return lNumber * lMultiplier;
            }
        }
    }
}

static inline DOUBLE inputFP(void)
{
    DOUBLE dInt = 0.0;
    DOUBLE dFrac = 0.0;
    DOUBLE dMultiplier = 1.0;
    DWORD dwFpCnt = 0;
    DOUBLE *pdCur = &dInt;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                dMultiplier = -1;
            }
        }
        if ('.' == c) {
            pdCur = &dFrac;
        } else if (('0' <= c) && (c <= '9')) {
            (*pdCur) *= 10;
            (*pdCur) += (DOUBLE)(c - '0');
            bRead = true;
            if (pdCur == &dFrac) {
                dwFpCnt++;
            }
        } else {
            if (bRead) {
                return dMultiplier * (dInt + dFrac / (pow((DOUBLE)10.0 , (DOUBLE)dwFpCnt)));
            }
        }
    }
}

/*----------------------------------------------*/
/**
 *  mod による操作ライブラリ
 */
#define ANS_MOD (1000000007)

class MODINT {
    static SQWORD MOD;
    SQWORD m_x;

public:
    MODINT(SQWORD val) {
        m_x = (val % MOD + MOD) % MOD;
    };
    MODINT() {
        m_x = 0;
    }
    static void Init(SQWORD sqMod) {
        MOD = sqMod;
    }

	MODINT& operator+= (const MODINT a)
    {
        m_x = (m_x + a.m_x) % MOD; 
        return *this;
    };
	MODINT& operator-= (const MODINT a)
    { 
        m_x = (m_x - a.m_x + MOD) % MOD; 
        return *this;
    };
	MODINT& operator*= (const MODINT a)
    {
        m_x = (m_x * a.m_x) % MOD;
        return *this;
    };
    MODINT pow(SQWORD t) const {
        if (!t) return 1;
        MODINT a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }
	MODINT operator+ (const MODINT a) const {
		MODINT res(*this);
		return (res += a);
	}
	MODINT operator- (const MODINT a) const {
		MODINT res(*this);
		return (res -= a);
	}
	MODINT operator* (const MODINT a) const {
		MODINT res(*this);
		return (res *= a);
	}
	MODINT operator/ (const MODINT a) const {
		MODINT res(*this);
		return (res /= a);
	}

    /* 逆元 */
    MODINT inv() const {
        return pow(MOD-2);
    }

    /* 除算 */
    MODINT& operator/=(const MODINT a) {
        return (*this) *= a.inv();
    } 

    /* 整数版 */
	MODINT& operator+= (const SQWORD a) {*this += MODINT(a); return *this;};
	MODINT& operator-= (const SQWORD a) {*this -= MODINT(a); return *this;};
	MODINT& operator*= (const SQWORD a) {*this *= MODINT(a); return *this;};
	MODINT& operator/= (const SQWORD a) {*this /= MODINT(a); return *this;};

    SQWORD getVal() { return m_x; };
};
SQWORD MODINT::MOD = ANS_MOD;


/*----------------------------------------------*/

#define EPS 1e-10
DOUBLE double_add(DOUBLE a, DOUBLE b) {
    if (ABS(a + b) < EPS * (ABS(a) + ABS(b))) {
        return 0;
    }
    return a+b;
}

struct VECTOR_2D {
    DOUBLE dX;
    DOUBLE dY;
    VECTOR_2D(DOUBLE x, DOUBLE y) : dX(x), dY(y) {};
    VECTOR_2D() : dX(0), dY(0) {};

    /* 加算 */
	VECTOR_2D& operator+= (const VECTOR_2D a)
    { 
        dX = dX + a.dX;
        dY = dY + a.dY;
        return *this;
    };
    const VECTOR_2D operator+ (const VECTOR_2D a) const {
		return VECTOR_2D(dX + a.dX, dY + a.dY); 
    };

    /* 減算 */
	VECTOR_2D& operator-= (const VECTOR_2D a)
    { 
        dX = dX - a.dX;
        dY = dY - a.dY;
        return *this;
    };
    const VECTOR_2D operator- (const VECTOR_2D a) const {
		return VECTOR_2D(dX - a.dX, dY - a.dY);
    };

    /* 定数倍 */
	VECTOR_2D& operator*= (const DOUBLE a)
    { 
        dX = dX * a;
        dY = dY * a;
        return *this;
    };
    const VECTOR_2D operator* (const DOUBLE a) const {
		return VECTOR_2D(dX * a, dY * a); 
    };

    /* 比較 */
    bool operator< (const VECTOR_2D &a) {
        if (dX == a.dX) {
            return (dY < a.dY);
        }
        return dX < a.dX;
    }

    DOUBLE norm(void) const {
        return (dX * dX + dY * dY);
    }

    DOUBLE dist(void) const {
        return sqrtl(norm());
    }

    DOUBLE angle(void) const {
        return atan2(dY, dX);
    }

    DOUBLE dotproduct(const VECTOR_2D a) const {
        return double_add(dX * a.dX, dY * a.dY);
    }

    DOUBLE crossproduct(const VECTOR_2D a) const {
        return double_add(dX * a.dY, -dY * a.dX);
    }
};



/*----------------------------------------------*/

struct BALL_ST {
    DOUBLE dBegin;
    DOUBLE dEnd;

    BALL_ST (DOUBLE b, DOUBLE e) : dBegin(b), dEnd(e) {};
}; 

bool cmpBegin (const BALL_ST &a, const BALL_ST &b) {
    return a.dBegin < b.dBegin;
}

bool cmpEnd (const BALL_ST &a, const BALL_ST &b) {
    return a.dEnd < b.dEnd;
}

/**
 *  角度の扱い 
 */
static inline DOUBLE normalizeAngle(DOUBLE dAngle)
{
    DOUBLE dRet = dAngle;
    while (dRet < 0.0) {
        dRet += (2.0 * d_PI);
    }

    while ((2.0 * d_PI) < dAngle) {
        dRet -= (2.0 * d_PI);
    }

    return dRet;
}

#define MAX_N (1500)
int main(void)
{
    SQWORD sqN = inputSQWORD();
    SQWORD sqK = inputSQWORD();

    vector<BALL_ST> vecBalls;
    vecBalls.emplace_back(0, 0);    /* dp用にインデックスを1はじまりにするためのダミー */
    for (SQWORD sqIdx = 0; sqIdx < sqN; sqIdx++) {
        SQWORD sqX = inputSQWORD();
        SQWORD sqY = inputSQWORD();
        SQWORD sqR = inputSQWORD();

        VECTOR_2D stVec((DOUBLE)sqX, (DOUBLE)sqY);
        DOUBLE dAngle = normalizeAngle(stVec.angle());
        DOUBLE dDist  = stVec.dist();
        DOUBLE dRange = asin((DOUBLE)sqR / dDist);
    
        DOUBLE dBegin, dEnd;
        if (2 * d_PI < (dAngle + dRange)) {
            dBegin = 0.0;
            dEnd = dAngle + dRange - (2 * d_PI);
        } else {
            dBegin = MIN(MAX(dAngle - dRange, 0.0), d_PI);
            dEnd   = MIN(MAX(dAngle + dRange, 0.0), d_PI); 
        }



//        printf("%0.10f %0.10f\n", dBegin, dEnd);

        vecBalls.emplace_back(dBegin, dEnd);
    }
    sort(vecBalls.begin(), vecBalls.end(), cmpBegin);

    /**
     *  dp[j][k]    左端がk番目のボールで、
     *              j個を使っているときの最大の角度
     *  dp[j][k] = max(dp[j-1][0] + angle, dp[j-1][1] + angle, dp[j-1][2] + angle ,,,, dp[j-1][k-1] + angle)
     * 
     */
    static DOUBLE s_aadDpTbl[MAX_N + 1][MAX_N + 1];
    for (SQWORD sqIdxJ = 0; sqIdxJ <= sqN; sqIdxJ++) {
        for (SQWORD sqIdxK = 0; sqIdxK <= sqN; sqIdxK++) {
            s_aadDpTbl[sqIdxJ][sqIdxK] = 0;
        }
    }
    for (SQWORD sqIdxJ = 0; sqIdxJ < sqN; sqIdxJ++) {
        for (SQWORD sqIdxK = sqIdxJ; sqIdxK < sqN; sqIdxK++) {
            DOUBLE dPrevEnd = vecBalls[sqIdxK].dEnd;
            for (SQWORD sqNextBallIdx = sqIdxK + 1; sqNextBallIdx <= sqN; sqNextBallIdx++) {
                BALL_ST stBall = vecBalls[sqNextBallIdx];
                DOUBLE dAddAngle = 0;
                if (dPrevEnd < stBall.dBegin) {
                    dAddAngle = stBall.dEnd - stBall.dBegin;
//                printf("> [%lld %lld %lld] %llf ", sqIdxJ, sqIdxK, sqNextBallIdx, dAddAngle / d_PI);
                    s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx] 
                        = max(s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx], s_aadDpTbl[sqIdxJ][sqIdxK] + dAddAngle);
                } else {
                    if (dPrevEnd < stBall.dEnd) {
                        dAddAngle = stBall.dEnd - dPrevEnd;
                        s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx] 
                            = max(s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx], s_aadDpTbl[sqIdxJ][sqIdxK] + dAddAngle);
                    }
//                printf("< [%lld %lld %lld] %llf ", sqIdxJ, sqIdxK, sqNextBallIdx, dAddAngle / d_PI);
                }

            }
        }
//        printf("\n");
    }

    DOUBLE dAns = 0.0;
    for (SQWORD sqIdxJ = 1; sqIdxJ <= sqK; sqIdxJ++) {
        for (SQWORD sqIdxK = sqIdxJ; sqIdxK <= sqN; sqIdxK++) {
//            printf("%llf ", s_aadDpTbl[sqIdxJ][sqIdxK] / d_PI);
            dAns = max(dAns, s_aadDpTbl[sqIdxJ][sqIdxK]);
        }
//        printf("\n");
    }

    printf("%0.11f\n", dAns / d_PI);

    return 0;
}
accuracy: 0.1267605633802817
time_ms: 490
memory_kb: 21112
final_rank: 19

code_snippet: #pragma GCC optimize ("O3")

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <set>
#include <algorithm>
#include <numeric>
#include <list>
using namespace std;

using QWORD  = uint64_t;
using SQWORD = int64_t;
using DWORD  = uint32_t;
using SDWORD = int32_t;
using WORD   = uint16_t;
using SWORD  = int16_t;
using BYTE   = uint8_t;
using SBYTE  = int8_t;
using DOUBLE = double;
using FLOAT  = float;

#define MIN_SDWORD (-2147483648)
#define MAX_SDWORD (2147483647)
#define MIN_SBYTE (-128)
#define MAX_SBYTE (127)

#define MIN_SQWORD (0x8000000000000000)
#define MAX_SQWORD (0x7FFFFFFFFFFFFFFF)

#define MAX_QWORD  (0xFFFFFFFFFFFFFFFF)
#define MAX_DWORD  (0xFFFFFFFF)
#define MAX_WORD   (0xFFFF)
#define MAX_BYTE   (0xFF)

#define MAX_DOUBLE      (1.0e+308)
#define DOUBLE_EPS      (1.0e-12)
#define MIN_DOUBLE_N    (-1.0e+308)

#define ArrayLength(a)  (sizeof(a) / sizeof(a[0]))

static inline DOUBLE MAX(DOUBLE a, DOUBLE b) { return a > b ? a : b; }
static inline QWORD MAX(QWORD a, QWORD b) { return a > b ? a : b; }
static inline DWORD MAX(DWORD a, DWORD b) { return a > b ? a : b; }
static inline SDWORD MAX(SDWORD a, SDWORD b) { return a > b ? a : b; }
static inline DOUBLE MIN(DOUBLE a, DOUBLE b) { return a < b ? a : b; }
static inline QWORD MIN(QWORD a, QWORD b) { return a < b ? a : b; }
static inline DWORD MIN(DWORD a, DWORD b) { return a < b ? a : b; }
static inline SDWORD MIN(SDWORD a, SDWORD b) { return a < b ? a : b; }
static inline DOUBLE ABS(DOUBLE a) { return 0 < a ? a : -a; };

#define BYTE_BITS   (8)
#define WORD_BITS   (16)
#define DWORD_BITS  (32)
#define QWORD_BITS  (64)

#define ANS_MOD (1000000007)

static const DOUBLE d_PI = 3.14159265358979323846;


static inline void inputStringSpSeparated(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c) || (' ' == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}

static inline void inputString(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}


static inline SQWORD inputSQWORD(void)
{
    SQWORD sqNumber = 0;
    SQWORD sqMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                sqMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            sqNumber *= 10LL;
            sqNumber += (SQWORD)(c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return sqNumber * sqMultiplier;
            }
        }
    }
}


static inline SDWORD inputSDWORD(void)
{
    SDWORD lNumber = 0;
    SDWORD lMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                lMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            lNumber *= 10;
            lNumber += (c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return lNumber * lMultiplier;
            }
        }
    }
}

static inline DOUBLE inputFP(void)
{
    DOUBLE dInt = 0.0;
    DOUBLE dFrac = 0.0;
    DOUBLE dMultiplier = 1.0;
    DWORD dwFpCnt = 0;
    DOUBLE *pdCur = &dInt;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                dMultiplier = -1;
            }
        }
        if ('.' == c) {
            pdCur = &dFrac;
        } else if (('0' <= c) && (c <= '9')) {
            (*pdCur) *= 10;
            (*pdCur) += (DOUBLE)(c - '0');
            bRead = true;
            if (pdCur == &dFrac) {
                dwFpCnt++;
            }
        } else {
            if (bRead) {
                return dMultiplier * (dInt + dFrac / (pow((DOUBLE)10.0 , (DOUBLE)dwFpCnt)));
            }
        }
    }
}

/*----------------------------------------------*/
/**
 *  mod による操作ライブラリ
 */
#define ANS_MOD (1000000007)

class MODINT {
    static SQWORD MOD;
    SQWORD m_x;

public:
    MODINT(SQWORD val) {
        m_x = (val % MOD + MOD) % MOD;
    };
    MODINT() {
        m_x = 0;
    }
    static void Init(SQWORD sqMod) {
        MOD = sqMod;
    }

	MODINT& operator+= (const MODINT a)
    {
        m_x = (m_x + a.m_x) % MOD; 
        return *this;
    };
	MODINT& operator-= (const MODINT a)
    { 
        m_x = (m_x - a.m_x + MOD) % MOD; 
        return *this;
    };
	MODINT& operator*= (const MODINT a)
    {
        m_x = (m_x * a.m_x) % MOD;
        return *this;
    };
    MODINT pow(SQWORD t) const {
        if (!t) return 1;
        MODINT a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }
	MODINT operator+ (const MODINT a) const {
		MODINT res(*this);
		return (res += a);
	}
	MODINT operator- (const MODINT a) const {
		MODINT res(*this);
		return (res -= a);
	}
	MODINT operator* (const MODINT a) const {
		MODINT res(*this);
		return (res *= a);
	}
	MODINT operator/ (const MODINT a) const {
		MODINT res(*this);
		return (res /= a);
	}

    /* 逆元 */
    MODINT inv() const {
        return pow(MOD-2);
    }

    /* 除算 */
    MODINT& operator/=(const MODINT a) {
        return (*this) *= a.inv();
    } 

    /* 整数版 */
	MODINT& operator+= (const SQWORD a) {*this += MODINT(a); return *this;};
	MODINT& operator-= (const SQWORD a) {*this -= MODINT(a); return *this;};
	MODINT& operator*= (const SQWORD a) {*this *= MODINT(a); return *this;};
	MODINT& operator/= (const SQWORD a) {*this /= MODINT(a); return *this;};

    SQWORD getVal() { return m_x; };
};
SQWORD MODINT::MOD = ANS_MOD;


/*----------------------------------------------*/

#define EPS 1e-10
DOUBLE double_add(DOUBLE a, DOUBLE b) {
    if (ABS(a + b) < EPS * (ABS(a) + ABS(b))) {
        return 0;
    }
    return a+b;
}

struct VECTOR_2D {
    DOUBLE dX;
    DOUBLE dY;
    VECTOR_2D(DOUBLE x, DOUBLE y) : dX(x), dY(y) {};
    VECTOR_2D() : dX(0), dY(0) {};

    /* 加算 */
	VECTOR_2D& operator+= (const VECTOR_2D a)
    { 
        dX = dX + a.dX;
        dY = dY + a.dY;
        return *this;
    };
    const VECTOR_2D operator+ (const VECTOR_2D a) const {
		return VECTOR_2D(dX + a.dX, dY + a.dY); 
    };

    /* 減算 */
	VECTOR_2D& operator-= (const VECTOR_2D a)
    { 
        dX = dX - a.dX;
        dY = dY - a.dY;
        return *this;
    };
    const VECTOR_2D operator- (const VECTOR_2D a) const {
		return VECTOR_2D(dX - a.dX, dY - a.dY);
    };

    /* 定数倍 */
	VECTOR_2D& operator*= (const DOUBLE a)
    { 
        dX = dX * a;
        dY = dY * a;
        return *this;
    };
    const VECTOR_2D operator* (const DOUBLE a) const {
		return VECTOR_2D(dX * a, dY * a); 
    };

    /* 比較 */
    bool operator< (const VECTOR_2D &a) {
        if (dX == a.dX) {
            return (dY < a.dY);
        }
        return dX < a.dX;
    }

    DOUBLE norm(void) const {
        return (dX * dX + dY * dY);
    }

    DOUBLE dist(void) const {
        return sqrtl(norm());
    }

    DOUBLE angle(void) const {
        return atan2(dY, dX);
    }

    DOUBLE dotproduct(const VECTOR_2D a) const {
        return double_add(dX * a.dX, dY * a.dY);
    }

    DOUBLE crossproduct(const VECTOR_2D a) const {
        return double_add(dX * a.dY, -dY * a.dX);
    }
};



/*----------------------------------------------*/

struct BALL_ST {
    DOUBLE dBegin;
    DOUBLE dEnd;

    BALL_ST (DOUBLE b, DOUBLE e) : dBegin(b), dEnd(e) {};
}; 

bool cmpBegin (const BALL_ST &a, const BALL_ST &b) {
    return a.dBegin < b.dBegin;
}

bool cmpEnd (const BALL_ST &a, const BALL_ST &b) {
    return a.dEnd < b.dEnd;
}

/**
 *  角度の扱い 
 */
static inline DOUBLE normalizeAngle(DOUBLE dAngle)
{
    DOUBLE dRet = dAngle;
    while (dRet < 0.0) {
        dRet += (2.0 * d_PI);
    }

    while ((2.0 * d_PI) < dAngle) {
        dRet -= (2.0 * d_PI);
    }

    return dRet;
}

#define MAX_N (1500)
int main(void)
{
    SQWORD sqN = inputSQWORD();
    SQWORD sqK = inputSQWORD();

    vector<BALL_ST> vecBalls;
    vecBalls.emplace_back(0, 0);    /* dp用にインデックスを1はじまりにするためのダミー */
    for (SQWORD sqIdx = 0; sqIdx < sqN; sqIdx++) {
        SQWORD sqX = inputSQWORD();
        SQWORD sqY = inputSQWORD();
        SQWORD sqR = inputSQWORD();

        VECTOR_2D stVec((DOUBLE)sqX, (DOUBLE)sqY);
        DOUBLE dAngle = normalizeAngle(stVec.angle());
        DOUBLE dDist  = stVec.dist();
        DOUBLE dRange = asin((DOUBLE)sqR / dDist);
    
        DOUBLE dBegin, dEnd;
        if (2 * d_PI < (dAngle + dRange)) {
            dBegin = 0.0;
            dEnd = dAngle + dRange - (2 * d_PI);
        } else {
            dBegin = MIN(MAX(dAngle - dRange, 0.0), d_PI);
            dEnd   = MIN(dAngle + dRange, d_PI); 
        }



//        printf("%0.10f %0.10f\n", dBegin, dEnd);

        vecBalls.emplace_back(dBegin, dEnd);
    }
    sort(vecBalls.begin(), vecBalls.end(), cmpBegin);

    /**
     *  dp[j][k]    左端がk番目のボールで、
     *              j個を使っているときの最大の角度
     *  dp[j][k] = max(dp[j-1][0] + angle, dp[j-1][1] + angle, dp[j-1][2] + angle ,,,, dp[j-1][k-1] + angle)
     * 
     */
    static DOUBLE s_aadDpTbl[MAX_N + 1][MAX_N + 1];
    for (SQWORD sqIdxJ = 0; sqIdxJ <= sqN; sqIdxJ++) {
        for (SQWORD sqIdxK = 0; sqIdxK <= sqN; sqIdxK++) {
            s_aadDpTbl[sqIdxJ][sqIdxK] = 0;
        }
    }
    for (SQWORD sqIdxJ = 0; sqIdxJ < sqN; sqIdxJ++) {
        for (SQWORD sqIdxK = sqIdxJ; sqIdxK < sqN; sqIdxK++) {
            DOUBLE dPrevEnd = vecBalls[sqIdxK].dEnd;
            for (SQWORD sqNextBallIdx = sqIdxK; sqNextBallIdx <= sqN; sqNextBallIdx++) {
                BALL_ST stBall = vecBalls[sqNextBallIdx];
                DOUBLE dAddAngle;
                if (dPrevEnd < stBall.dBegin) {
                    dAddAngle = stBall.dEnd - stBall.dBegin;
//                printf("> [%lld %lld %lld] %llf ", sqIdxJ, sqIdxK, sqNextBallIdx, dAddAngle / d_PI);
                    s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx] 
                        = max(s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx], s_aadDpTbl[sqIdxJ][sqIdxK] + dAddAngle);
                } else {
                    if (dPrevEnd < stBall.dEnd) {
                        dAddAngle = max(0.0, stBall.dEnd - dPrevEnd);
                        s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx] 
                            = max(s_aadDpTbl[sqIdxJ + 1][sqNextBallIdx], s_aadDpTbl[sqIdxJ][sqIdxK] + dAddAngle);
                    }
//                printf("< [%lld %lld %lld] %llf ", sqIdxJ, sqIdxK, sqNextBallIdx, dAddAngle / d_PI);
                }

            }
        }
//        printf("\n");
    }

    DOUBLE dAns = 0.0;
    for (SQWORD sqIdxJ = 1; sqIdxJ <= sqK; sqIdxJ++) {
        for (SQWORD sqIdxK = sqIdxJ; sqIdxK <= sqN; sqIdxK++) {
//            printf("%llf ", s_aadDpTbl[sqIdxJ][sqIdxK] / d_PI);
            dAns = max(dAns, s_aadDpTbl[sqIdxJ][sqIdxK]);
        }
//        printf("\n");
    }

    printf("%0.11f\n", dAns / d_PI);

    return 0;
}
accuracy: 0.1267605633802817
time_ms: 540
memory_kb: 21088
final_rank: 20

code_snippet: #include <bits/stdc++.h>
#ifdef LOCAL
#include "../cxx-prettyprint/prettyprint.hpp"
#endif
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;

#define REP(i, n) for (int (i) = 0 ; (i) < (int)(n) ; ++(i))
#define REPN(i, m, n) for (int (i) = m ; (i) < (int)(n) ; ++(i))
#define REP_REV(i, n) for (int (i) = (int)(n) - 1 ; (i) >= 0 ; --(i))
#define REPN_REV(i, m, n) for (int (i) = (int)(n) - 1 ; (i) >= m ; --(i))
#define ALL(x) x.begin(), x.end()

#define INF ((1 << 29)-1)
#define MOD (1000000007)

#define print2D(h, w, arr) REP(i, h) { REP(j, w) cout << arr[i][j] << " "; cout << endl; }
template<class T> void print(const T& x){cout << x << endl;}
template<class T, class... A> void print(const T& first, const A&... rest) { cout << first << " "; print(rest...); }
struct PreMain {PreMain(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(20);}} premain;

// ベクトル
namespace Geom {

    const double eps = 1e-9;

    struct Point {
        double x, y;
        explicit Point(double x=0, double y=0): x(x), y(y) {}
        Point& operator+=(const Point& v){ x += v.x; y+= v.y; return *this;}
        Point operator+(const Point& v) const{return Point(*this) += v;}
        Point& operator-=(const Point& v){x -= v.x; y-= v.y; return *this;}
        Point operator-(const Point& v) const{return Point(*this) -= v;}
        Point& operator*=(double s){x *= s; y *= s; return *this;}
        Point operator*(double s) const{return Point(*this) *= s;}
        Point& operator/=(double s){x /= s; y /= s; return *this;}
        Point operator/(double s) const{return Point(*this) /= s;}
        double dot(const Point& v) const {return x*v.x + y*v.y;}        /* 内積 */
        double cross(const Point& v) const {return x*v.y - v.x*y;}      /* 外積 */
        double norm2() const {return x*x + y*y;}                        /* ノルムの二乗*/
        double norm() const {return sqrt(norm2());}                     /* ノルム */
        int quadrant() const { if(y > 0) return x>0 ? 1:2; else return x>0 ? 4:3;} /* 象限判定 */
        Point rot(double theta) {return Point(cos(theta) * x - sin(theta) * y, sin(theta) * x + cos(theta) * y);} // 回転
        Point rot90() {return Point(-y, x);} // 90度回転
    };

    ostream& operator<<(ostream& os, const Point& v) {os<<"("<<v.x<<","<<v.y<<")"; return os;}
    istream& operator>>(istream& is, Point& v){ is >> v.x >> v.y; return is;}

    // 点a, b, cからなる三角形の面積
    double calc_triangle_area(Point a, Point b, Point c) {
        Point v1 = b - a;
        Point v2 = c - a;
        return abs(v1.cross(v2)) / 2;
    }

    // 点a, bを通る直線と点cとの距離
    double calc_distance_between_point_and_line(Point a, Point b, Point c) {
        return abs((b-a).cross(c-a)) / (b-a).norm();
    }

    // 点a, bを端点とする線分と点cとの距離
    double calc_distance_between_point_and_segment(Point a, Point b, Point c) {
        if ((b-a).dot(c-a) < eps) return (c-a).norm();
        if ((a-b).dot(c-b) < eps) return (c-b).norm();
        return calc_distance_between_point_and_line(a, b, c);
    }

    // 点a, bを端点とする線分と点cと点dを端点とする線分の距離
    double calc_distance_between_segments(Point a, Point b, Point c, Point d) {
        double d0 = calc_distance_between_point_and_segment(a, b, c);
        double d1 = calc_distance_between_point_and_segment(a, b, d);
        double d2 = calc_distance_between_point_and_segment(c, d, a);
        double d3 = calc_distance_between_point_and_segment(c, d, b);
        return min(min(d0, d1), min(d2, d3));
    }

    enum RELATION_BETWEEN_SEGMENT_AND_POINT {
        COUNTER_CLOCKWISE = 1,     // p1とp2のp0を挟んだ位置関係が反時計回り
        CLOCKWISE = -1,            // 時計回り
        ONLINE_BACK = 2,           // p1とp2がp0を挟んで直線状にある
        ONLINE_FRONT = -2,         // p0とp2の間にp1がある
        ON_SEGMENT = 0,            // p0とp1の間にp2がある
    };

    // 点cが点a, bを端点とする線分のどちら側にあるか、enumで返す
    RELATION_BETWEEN_SEGMENT_AND_POINT ccw_ex(Point p0, Point p1, Point p2) {
        Point v1 = p1 - p0;
        Point v2 = p2 - p0;
        if(v1.cross(v2) > eps) return COUNTER_CLOCKWISE;    // 1
        if(v1.cross(v2) < -eps) return CLOCKWISE;           // -1
        if(v1.dot(v2) < -eps) return ONLINE_BACK;           // 2
        if(v1.norm() < v2.norm()) return ONLINE_FRONT;      // -2
        return ON_SEGMENT;                                  // 0
    }

    // 点cが点a, bを端点とする線分のどちら側にあるか
    int ccw(Point p0, Point p1, Point p2) {
        Point v1 = p1 - p0;
        Point v2 = p2 - p0;
        if(v1.cross(v2) > eps) return 1;
        if(v1.cross(v2) < -eps) return -1;
        return 0;
    }

    // p1,p2を端点とする線分Aとp3,p4を端点とする線分Bの交差判定
    // include_end=trueなら端点が重なっていても交差しているとみなす
    bool intersect(Point p1, Point p2, Point p3, Point p4, bool include_end=true) {

        bool is_otherside;
        bool is_inside;

        if (include_end){
            is_otherside = ccw(p1,p2,p3) * ccw(p1,p2,p4) <= 0; // Aの両側にBの端点があるかどうか。どちらかがAの直線状にいてもOK
            is_inside = ccw(p3,p4,p1) * ccw(p3,p4,p2) <= 0;    // Aの端点の内側にBがいるかどうか。
        } else {
            is_otherside = ccw(p1,p2,p3) * ccw(p1,p2,p4) < 0; // Aの両側にBの端点があるかどうか
            is_inside = ccw(p3,p4,p1) * ccw(p3,p4,p2) < 0;    // Aの端点の内側にBがいるかどうか
        }
        return is_otherside && is_inside;
    }


    // 円
    struct Circle {
        Point c;
        double r;
        Circle(){}
        Circle(Point c, double r):c(c),r(r){}

        // 円が点pを含むかどうか　include_circumは円周上を含むとするかどうか
        bool does_include_point(Point p, bool include_circum = true){
            double d = (p - c).norm();
            if (include_circum){
                return d < r + eps;
            } else {
                return d < r - eps;
            }
        }
    };

    // 点p1, p2を通る半径rの円を返す
    vector<Circle> calc_circle_on_two_points(Point p1, Point p2, double r){

        Point p12_half = (p2 - p1) / 2.0;

        double n_vec_norm2 = r*r - p12_half.norm2();
        if (n_vec_norm2 < 0) return vector<Circle>();

        double n_vec_norm = sqrt(n_vec_norm2);
        Point n_vec = p12_half.rot90() * n_vec_norm / p12_half.norm();

        vector<Circle> ret;
        ret.emplace_back(p1 + p12_half + n_vec, 1.0);
        ret.emplace_back(p1 + p12_half - n_vec, 1.0);
        return ret;
    }
}

double getRadian(double x, double y) {
    double radian = atan2(y, x);
    return radian;
}

double getDegree(double radian) {
    if(radian < 0) {
        radian = radian + 2 * M_PI;
    }
    return (radian*360) / (2*M_PI);
}

int main() {
#ifdef LOCAL
    ifstream in("../in.txt"); cin.rdbuf(in.rdbuf());
#endif

    using namespace Geom;

    int n, k;
    cin >> n >> k;

    vector<Point> point(n);
    vector<double> radius(n);
    vector<pair<double, double> > angle(n);
    REP(i, n) cin >> point[i] >> radius[i];

    REP(i, n) {
        double d = sqrt(point[i].x*point[i].x + point[i].y*point[i].y);
        double center_angle;
        if(point[i].x == 0) {
            if(point[i].y == 0) {
                cout << "1" << endl;
                return 0;
            } else if(point[i].y > 0) {
                center_angle = 90;
            } else {
                center_angle = 270;
            }
        } else {
            center_angle = getDegree(getRadian(point[i].x, point[i].y));
        }

        double center_tangent_angle = getDegree(getRadian(sqrt(d*d - radius[i]*radius[i]), radius[i]));
        angle[i].first = center_angle - center_tangent_angle;
        angle[i].second = center_angle + center_tangent_angle;
        if(0 <= center_angle && center_angle <= 90) {
            if(angle[i].first < 0){
                angle[i].first = 0;
            }
        }
        else if(center_angle <= 180) {
            if(angle[i].second > 180){
                angle[i].second = 180;
            }
        }
        else if(center_angle <= 270.0) {
            if(angle[i].first < 180){
                angle[i].second = 180;
            }
            else{
                angle[i].first = 0, angle[i].second = 0;
            }
        }
        else{
            if(angle[i].second > 360){
                angle[i].first = 0, angle[i].second -=360;
            }
            else{
                angle[i].first = 0, angle[i].second = 0;
            }
        }
        //printf("center = %f\n", center_angle);
        //printf("first = %f, second = %f\n", angle[i].first, angle[i].second);
    }

    REP(i, angle.size()){
        if(angle[i].first == 0 && angle[i].second == 0){
            angle.erase(angle.begin() + i);            
        }
    }

    /* 包含してるものを削除 */
    REP(i, angle.size()) REP(j, angle.size()){
        if(i == j) continue;
        if(angle[j].first <= angle[i].first && angle[i].second <= angle[j].second) {
            angle.erase(angle.begin() + i);
            i--;
            break;
        }
    }

    REP(i, angle.size()){
        //printf("first = %f, second = %f\n", angle[i].first, angle[i].second);
    }

    angle.insert(angle.begin(), {0, 0});
    sort(angle.begin(), angle.end());

    vector<vector<double> > dp;
    dp.assign(n+1, vector<double>(k+1, 0));

    int N = angle.size()-1;
    REPN(i, 1, N + 1){
        //
        int l = i;
        while (l > 0){
            l--;
            if (angle[l].second < angle[i].first){
                break;
            }
        }
        REPN(j, 1, k+1){
            dp[i][j] = dp[i-1][j];
            dp[i][j] = max(dp[i][j], dp[l][j-1] + angle[i].second - angle[i].first);
            dp[i][j] = max(dp[i][j], dp[l+1][j-1] + angle[i].second - angle[l+1].second);
        }
    }

    print(dp[N][k] / 180);


    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 20884
final_rank: 1

code_snippet: #define _USE_MATH_DEFINES
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
#include <numeric>
#include <tuple>
#include <iomanip>
#include <assert.h>

#define sqr(x) std::pow(x, 2.0)
#define INF 1e10
#define EPS 1e-10
#define REP(i, n) for (int i = 0; i < n; i++)
#define POS_OR_INF(x) (x > 0 ? x : INF)

using namespace std;

using ld = long double;

struct Point {
	Point() = default;
	Point(ld x, ld y) : x(x), y(y) {}
	Point(const Point& s, const Point& e) : x(e.x - s.x), y(e.y - s.y) {}

	Point normalized(void) const {
		return Point(x / norm(), y / norm());
	}

	ld norm(void) const {
		return sqrt(x * x + y * y);
	}

	Point flipped(void) const {
		return Point(-x, -y);
	}

	Point normal_vector(bool normalize = false) const {
		auto vec = Point(-y, x);
		return normalize ? vec.normalized() : vec;
	}

	ld x, y;
};

using Vector = Point;

inline Vector points2vec(const Point& s, const Point& e) {
	return Vector(e.x - s.x, e.y - s.y);
}

inline ld distance(const Point& s, const Point& e) {
	return points2vec(s, e).norm();
}

inline ld distance_square(const Point& s, const Point& e) {
	return pow(points2vec(s, e).norm(), 2.0);
}

inline Vector operator * (const Vector& l, ld r) {
	return Vector(l.x * r, l.y * r);
}

inline Vector operator * (ld l, const Vector& r) {
	return r * l;
}

inline Vector operator / (const Vector& l, ld r) {
	return Vector(l.x / r, l.y / r);
}

inline Point operator + (const Point& l, const Point& r) {
	return Point(l.x + r.x, l.y + r.y);
}

inline Point operator - (const Point& l, const Point& r) {
	return Point(l.x - r.x, l.y - r.y);
}

inline istream& operator >> (istream& is, Point& p) {
	return is >> p.x >> p.y;
}

int main(int argc, char** argv) {
	int N, K;

	cin >> N >> K;
	cout << fixed << setprecision(20);

	vector<pair<double, double>> a(N), b;

	for (int i = 0; i < N; i++) {
		Point p;
		double r;
		cin >> p >> r;

		double theta = asin(r/p.norm());
		double rad = atan2(p.y, p.x);

		if (rad < -M_PI / 2) rad += 2 * M_PI;

		a[i].first = min(M_PI, max(0.0, rad - theta));
		a[i].second = min(M_PI, max(0.0, rad + theta));
	}

	for (int i = 0; i < N; i++) {
		bool included = false;
		for (int j = 0; j < N; j++) {
			if (a[i].first > a[j].first && a[i].second < a[j].second)
				included = true;
		}
		if (!included) {
			b.push_back(a[i]);
		}
	}

	sort(b.begin(), b.end());

	int M = b.size();

	vector<vector<double>> dp(K + 1, vector<double>(M + 1, 0));
	double ans = 0;

	for (int i = 1; i <= K; i++) {
		for (int j = 0; j < M; j++) {
			double best = 0;
			int k = 0;

			while (b[k].second < b[j].first) {
				best = max(best, dp[i-1][k]);
				k++;
			}
			
			dp[i][j] = max(dp[i][j], best + b[j].second - b[j].first);

			//for (; k < j; k++) {
			dp[i][j] = max(dp[i][j], dp[i-1][k] + b[j].second - b[k].second);
			//}
			ans = max(ans, dp[i][j]);
		}
	}

	cout << ans / M_PI;
}
accuracy: 1
time_ms: 340
memory_kb: 20696
final_rank: 13

code_snippet: // aribon3-6_f
#include <bits/stdc++.h>
#ifdef LOCAL
#include "../cxx-prettyprint/prettyprint.hpp"
#endif
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;

#define REP(i, n) for (int (i) = 0 ; (i) < (int)(n) ; ++(i))
#define REPN(i, m, n) for (int (i) = m ; (i) < (int)(n) ; ++(i))
#define REP_REV(i, n) for (int (i) = (int)(n) - 1 ; (i) >= 0 ; --(i))
#define REPN_REV(i, m, n) for (int (i) = (int)(n) - 1 ; (i) >= m ; --(i))
#define ALL(x) x.begin(), x.end()

#define INF ((1 << 29)-1)
#define MOD (1000000007)

#define print2D(h, w, arr) REP(i, h) { REP(j, w) cout << arr[i][j] << " "; cout << endl; }
template<class T> void print(const T& x){cout << x << endl;}
template<class T, class... A> void print(const T& first, const A&... rest) { cout << first << " "; print(rest...); }
struct PreMain {PreMain(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(20);}} premain;

// ベクトル
namespace Geom {
    #define _USE_MATH_DEFINES

    const double eps = 1e-9;

    struct Point {
        double x, y;
        explicit Point(double x=0, double y=0): x(x), y(y) {}
        Point& operator+=(const Point& v){ x += v.x; y+= v.y; return *this;}
        Point operator+(const Point& v) const{return Point(*this) += v;}
        Point& operator-=(const Point& v){x -= v.x; y-= v.y; return *this;}
        Point operator-(const Point& v) const{return Point(*this) -= v;}
        Point& operator*=(double s){x *= s; y *= s; return *this;}
        Point operator*(double s) const{return Point(*this) *= s;}
        Point& operator/=(double s){x /= s; y /= s; return *this;}
        Point operator/(double s) const{return Point(*this) /= s;}
        double dot(const Point& v) const {return x*v.x + y*v.y;}        /* 内積 */
        double cross(const Point& v) const {return x*v.y - v.x*y;}      /* 外積 */
        double norm2() const {return x*x + y*y;}                        /* ノルムの二乗*/
        double norm() const {return sqrt(norm2());}                     /* ノルム */
        int quadrant() const { if(y > 0) return x>0 ? 1:2; else return x>0 ? 4:3;} /* 象限判定 */
        Point rot(double theta) {return Point(cos(theta) * x - sin(theta) * y, sin(theta) * x + cos(theta) * y);} // 回転
        Point rot90() {return Point(-y, x);} // 90度回転
    };
    ostream& operator<<(ostream& os, const Point& v) {os<<"("<<v.x<<","<<v.y<<")"; return os;}
    istream& operator>>(istream& is, Point& v){ is >> v.x >> v.y; return is;}

    // 点a, b, cからなる三角形の面積
    double calc_triangle_area(Point a, Point b, Point c) {
        Point v1 = b - a;
        Point v2 = c - a;
        return abs(v1.cross(v2)) / 2;
    }

    // 点a, bを通る直線と点cとの距離
    double calc_distance_between_point_and_line(Point a, Point b, Point c) {
        return abs((b-a).cross(c-a)) / (b-a).norm();
    }

    // 点a, bを端点とする線分と点cとの距離
    double calc_distance_between_point_and_segment(Point a, Point b, Point c) {
        if ((b-a).dot(c-a) < eps) return (c-a).norm();
        if ((a-b).dot(c-b) < eps) return (c-b).norm();
        return calc_distance_between_point_and_line(a, b, c);
    }

    // 点a, bを端点とする線分と点cと点dを端点とする線分の距離
    double calc_distance_between_segments(Point a, Point b, Point c, Point d) {
        double d0 = calc_distance_between_point_and_segment(a, b, c);
        double d1 = calc_distance_between_point_and_segment(a, b, d);
        double d2 = calc_distance_between_point_and_segment(c, d, a);
        double d3 = calc_distance_between_point_and_segment(c, d, b);
        return min(min(d0, d1), min(d2, d3));
    }

    enum RELATION_BETWEEN_SEGMENT_AND_POINT {
        COUNTER_CLOCKWISE = 1,     // p1とp2のp0を挟んだ位置関係が反時計回り
        CLOCKWISE = -1,            // 時計回り
        ONLINE_BACK = 2,           // p1とp2がp0を挟んで直線状にある
        ONLINE_FRONT = -2,         // p0とp2の間にp1がある
        ON_SEGMENT = 0,            // p0とp1の間にp2がある
    };

    // 点cが点a, bを端点とする線分のどちら側にあるか、enumで返す
    RELATION_BETWEEN_SEGMENT_AND_POINT ccw_ex(Point p0, Point p1, Point p2) {
        Point v1 = p1 - p0;
        Point v2 = p2 - p0;
        if(v1.cross(v2) > eps) return COUNTER_CLOCKWISE;    // 1
        if(v1.cross(v2) < -eps) return CLOCKWISE;           // -1
        if(v1.dot(v2) < -eps) return ONLINE_BACK;           // 2
        if(v1.norm() < v2.norm()) return ONLINE_FRONT;      // -2
        return ON_SEGMENT;                                  // 0
    }

    // 点cが点a, bを端点とする線分のどちら側にあるか
    int ccw(Point p0, Point p1, Point p2) {
        Point v1 = p1 - p0;
        Point v2 = p2 - p0;
        if(v1.cross(v2) > eps) return 1;
        if(v1.cross(v2) < -eps) return -1;
        return 0;
    }

    // p1,p2を端点とする線分Aとp3,p4を端点とする線分Bの交差判定
    // include_end=trueなら端点が重なっていても交差しているとみなす
    bool intersect(Point p1, Point p2, Point p3, Point p4, bool include_end=true) {

        bool is_otherside;
        bool is_inside;

        if (include_end){
            is_otherside = ccw(p1,p2,p3) * ccw(p1,p2,p4) <= 0; // Aの両側にBの端点があるかどうか。どちらかがAの直線状にいてもOK
            is_inside = ccw(p3,p4,p1) * ccw(p3,p4,p2) <= 0;    // Aの端点の内側にBがいるかどうか。
        } else {
            is_otherside = ccw(p1,p2,p3) * ccw(p1,p2,p4) < 0; // Aの両側にBの端点があるかどうか
            is_inside = ccw(p3,p4,p1) * ccw(p3,p4,p2) < 0;    // Aの端点の内側にBがいるかどうか
        }
        return is_otherside && is_inside;
    }


    // 円
    struct Circle {
        Point c;
        double r;
        Circle(){}
        Circle(Point c, double r):c(c),r(r){}

        // 円が点pを含むかどうか　include_circumは円周上を含むとするかどうか
        bool does_include_point(Point p, bool include_circum = true){
            double d = (p - c).norm();
            if (include_circum){
                return d < r + eps;
            } else {
                return d < r - eps;
            }
        }
    };
    ostream& operator<<(ostream& os, const Circle& c) {os<<"("<<c.c<<","<<c.r<<")"; return os;}
    istream& operator>>(istream& is, Circle& c){ is >> c.c >> c.r; return is;}

    // 点p1, p2を通る半径rの円を返す
    vector<Circle> calc_circle_on_two_points(Point p1, Point p2, double r){

        Point p12_half = (p2 - p1) / 2.0;

        double n_vec_norm2 = r*r - p12_half.norm2();
        if (n_vec_norm2 < 0) return vector<Circle>();

        double n_vec_norm = sqrt(n_vec_norm2);
        Point n_vec = p12_half.rot90() * n_vec_norm / p12_half.norm();

        vector<Circle> ret;
        ret.emplace_back(p1 + p12_half + n_vec, 1.0);
        ret.emplace_back(p1 + p12_half - n_vec, 1.0);
        return ret;
    }

    // 点pを通る、円Cの２つの接線の傾きの角度を返す [0, 2π]で返す
    pair<double, double> calc_tangent_line_on_circle(Circle c, Point p){
        Point pc = c.c - p;
        double angle0 = atan2(pc.y, pc.x);
        double l2 = pc.norm2() - c.r*c.r;
        if (l2 < 0) {
            return {0, 2*M_PI};
        }
        double l = sqrt(l2);
        double angle1 = angle0 - atan2(c.r, l);
        double angle2 = angle0 + atan2(c.r, l);
        angle1 = angle1 >= 0 ? angle1 : angle1 + 2*M_PI;
        angle2 = angle2 >= 0 ? angle2 : angle2 + 2*M_PI;

        return {angle1, angle2};
    }

}


int main() {
#ifdef LOCAL
    ifstream in("../arg.txt"); cin.rdbuf(in.rdbuf());
#endif

    using namespace Geom;

    int N, K;
    cin >> N >> K;
    vector<Circle> circles(N);
    REP(i, N) cin >> circles[i];

    vector<pair<double, double>> intervals(N);
    REP(i, N){
        auto thetas = calc_tangent_line_on_circle(circles[i], Point(0.0, 0.0));
        if (thetas.first == 0 && thetas.second == 2*M_PI) {
            print(1.0);
            return 0;
        }

        if (thetas.first >= M_PI && thetas.second >= M_PI){
            intervals[i] = {0, 0};
        } else if (thetas.first >= M_PI) {
            intervals[i] = {0, thetas.second};
        } else if (thetas.second >= M_PI){
            intervals[i] = {thetas.first, M_PI};
        } else {
            intervals[i] = {thetas.first, thetas.second};
        }
    }

    // 他の要素に包含される要素を削除
    REP(i, intervals.size()) REP(j, intervals.size()){
        if (i == j) continue;

        if (intervals[j].first <= intervals[i].first && intervals[i].second <= intervals[j].second) {
            intervals.erase(intervals.begin() + i);
            i--;
            break;
        }
    }

    intervals.insert(intervals.begin(), {0, 0});
    sort(ALL(intervals));

    vector<vector<double>> dp;
    dp.assign(N+1, vector<double>(K+1, 0));

    int n = intervals.size()-1;
    REPN(i, 1, n+1){
        //
        int l = i;
        while (l > 0){
            l--;
            if (intervals[l].second < intervals[i].first){
                break;
            }
        }
        REPN(j, 1, K+1){
            dp[i][j] = dp[i-1][j];
            dp[i][j] = max(dp[i][j], dp[l][j-1] + intervals[i].second - intervals[i].first);
            dp[i][j] = max(dp[i][j], dp[l+1][j-1] + intervals[i].second - intervals[l+1].second);
        }
    }

    print(dp[n][K] / M_PI);

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 20988
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef pair<double,double> PA;

int n,k;
vector<PA> p;
double memo[1510][1510];

double dp(int a,int b){
    
    if(b >= k) return 0;
    if(memo[a][b] != -1.0) return memo[a][b];
    
    double res,add;
    int i,num;
    res = 0;
    add = 0;
    num = a+1;
    for(i=a+1;i<p.size()&&p[i].first<p[a].second;i++){
        if(add < p[i].second-p[a].second){
            num = i;
            add = p[i].second-p[a].second;
        }
    }
    if(i != a+1) res = max(res,dp(num,b+1)+add);
    for(int j=i;j<p.size();j++){
        add = p[j].second-p[j].first;
        res = max(res,dp(j,b+1)+add);
    }
    
    return memo[a][b] = res;
}

int main()
{
    
    double x,y,r,as,at,ll,rr;
    vector<PA> vec;
    
    scanf("%d %d",&n,&k);
    for(int i=0;i<n;i++){
        scanf("%lf %lf %lf",&x,&y,&r);
        if(y+r < 0) continue;
        as = asin(r/sqrt(x*x+y*y));
        at = atan2(y,x);
        ll = at-as;
        rr = at+as;
        if(ll < -M_PI){
            ll += 2*M_PI;
            rr += 2*M_PI;
        }
        vec.push_back( PA(max(0.0,ll),min(M_PI,rr)) );
    }
    
    sort(vec.begin(),vec.end());
    
    double ma = 0.0;
    p.push_back(PA(0.0,0.0));
    for(int i=0;i<vec.size();i++){
        if(ma == M_PI) break;
        if(ma < vec[i].second){
            if(i < vec.size()-1 && vec[i].first == vec[i+1].first) continue;
            ma = vec[i].second;
            p.push_back(vec[i]);
        }
    }
    fill_n(*memo,1510*1510,-1.0);
    printf("%.13f\n",dp(0,0)/M_PI);
    
    return(0);
}
accuracy: 1
time_ms: 540
memory_kb: 21616
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i,x,y) for(int i=(x);i<(y);++i)
#define mp(a,b) make_pair((a),(b))
#define debug(x) #x << "=" << (x)
 
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define dump(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define dump(x)
#endif

typedef long long int ll;
typedef pair<int,int> pii;
//template<typename T> using vec=std::vector<T>;

const int INF=1<<30;
const long long int INF_=1LL<<58;
const double EPS=1e-9;
const int dx[]={1,0,-1,0},dy[]={0,1,0,-1};

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec){
	os << "[";
	for (const auto &v : vec) {
		os << v << ",";
	}
	os << "]";
	return os;
}

void Solve(){
	int n,K;
	scanf("%d%d",&n,&K);

	vector<pair<double,double>> ps;
	const double PI=3.14159265359;
	rep(i,0,n){
		double x,y,r;
		scanf("%lf%lf%lf",&x,&y,&r);
		if(y+r<=0) continue;
		if(y-r<=0){
			double f,s;
			if(x<0){
				f=atan2(y,x)-asin(r/sqrt(x*x+y*y));
				s=PI;
			}else{
				f=0;
				s=atan2(y,x)+asin(r/sqrt(x*x+y*y));
			}
			while(f<0) f+=PI;
			while(s<0) s+=PI;
			ps.push_back(mp(f,s));
		}else ps.push_back(mp(atan2(y,x)-asin(r/sqrt(x*x+y*y)),atan2(y,x)+asin(r/sqrt(x*x+y*y))));
	}
	
	sort(ps.begin(),ps.end());
	ps.erase(unique(ps.begin(),ps.end()),ps.end()); //同じ区間があると次の処理で面倒なので消しておく

	//他の区間に完全に包含されているものを取り除く
	vector<pair<double,double>> tmp;
	rep(i,0,ps.size()){
		bool ok=true;
		rep(j,0,ps.size()){
			if(i==j) continue;
			if(ps[j].first<=ps[i].first&&ps[i].second<=ps[j].second){
				ok=false;
				break;
			}
		}
		if(ok) tmp.push_back(ps[i]);
	}
	ps=tmp;

	if(ps.size()==0){
		cout << 0 << endl;
		return;
	}

	vector<int> a(ps.size()); //a[i]=i番目の区間とギリギリ重なってる区間。存在しない場合はもっとも近いやつ
	rep(i,1,ps.size()){
		rep(j,0,i+1){
			if(ps[j].second>=ps[i].first){
				a[i]=j;
				break;
			}
		}
		if(a[i]==i) a[i]=i-1;
	}

	static double dp[1500][1501][2]; //dp[i][j][k]=i番目の区間まででj個取って、i番目の区間を使った(k==1)or使わなかった(k==0)ときの最大
	dp[0][0][0]=0;
	dp[0][1][1]=ps[0].second-ps[0].first;
	double ans=dp[0][1][1];
	rep(i,1,ps.size()){
		rep(j,0,K+1){
			dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1]);
			if(j==0) continue;
			//a[i]番目の区間を使った場合は重複している部分を取り除く、使わなかった場合は重なっていないのでそのまま足す。
			dp[i][j][1]=max(dp[a[i]][j-1][1]+ps[i].second-max(ps[i].first,ps[a[i]].second),dp[a[i]][j-1][0]+ps[i].second-ps[i].first);
			ans=max({ans,dp[i][j][1],dp[i][j][0]});
		}
	}

	printf("%.10lf\n",ans/PI);
}

int main(){
	Solve();
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 36584
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i,x,y) for(int i=(x);i<(y);++i)
#define mp(a,b) make_pair((a),(b))
#define debug(x) #x << "=" << (x)
 
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define dump(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define dump(x)
#endif

typedef long long int ll;
typedef pair<int,int> pii;
//template<typename T> using vec=std::vector<T>;

const int INF=1<<30;
const long long int INF_=1LL<<58;
const double EPS=1e-9;
const int dx[]={1,0,-1,0},dy[]={0,1,0,-1};

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec){
	os << "[";
	for (const auto &v : vec) {
		os << v << ",";
	}
	os << "]";
	return os;
}

void Solve(){
	int n,K;
	scanf("%d%d",&n,&K);

	vector<pair<double,double>> ps;
	const double PI=3.14159265359;
	rep(i,0,n){
		double x,y,r;
		scanf("%lf%lf%lf",&x,&y,&r);
		if(y+r<=0) continue;
		if(y-r<=0){
			double f,s;
			if(x<0){
				f=atan2(y,x)-asin(r/sqrt(x*x+y*y));
				s=PI;
			}else{
				f=0;
				s=atan2(y,x)+asin(r/sqrt(x*x+y*y));
			}
			while(f<0) f+=PI;
			while(s<0) s+=PI;
			ps.push_back(mp(f,s));
		}else ps.push_back(mp(atan2(y,x)-asin(r/sqrt(x*x+y*y)),atan2(y,x)+asin(r/sqrt(x*x+y*y))));
	}
	
	sort(ps.begin(),ps.end());
	ps.erase(unique(ps.begin(),ps.end()),ps.end());
	
	vector<pair<double,double>> tmp;
	rep(i,0,ps.size()){
		bool ok=true;
		rep(j,0,ps.size()){
			if(i==j) continue;
			if(ps[j].first<=ps[i].first&&ps[i].second<=ps[j].second){
				ok=false;
				break;
			}
		}
		if(ok) tmp.push_back(ps[i]);
	}
	ps=tmp;

	if(ps.size()==0){
		cout << 0 << endl;
		return;
	}

	vector<int> a(ps.size());
	rep(i,1,ps.size()){
		rep(j,0,i+1){
			if(ps[j].second>=ps[i].first){
				a[i]=j;
				break;
			}
		}
		if(a[i]==i) a[i]=i-1;
	}

	static double dp[1500][1501][2];
	dp[0][0][0]=0;
	dp[0][1][1]=ps[0].second-ps[0].first;
	double ans=dp[0][1][1];
	rep(i,1,ps.size()){
		rep(j,0,K+1){
			dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1]);
			if(j==0) continue;
			dp[i][j][1]=max(dp[a[i]][j-1][1]+ps[i].second-max(ps[i].first,ps[a[i]].second),dp[a[i]][j-1][0]+ps[i].second-ps[i].first);
			ans=max({ans,dp[i][j][1],dp[i][j][0]});
		}
	}

	printf("%.10lf\n",ans/PI);
}

int main(){
	Solve();
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 36584
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i,x,y) for(int i=(x);i<(y);++i)
#define mp(a,b) make_pair((a),(b))
#define debug(x) #x << "=" << (x)
 
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define dump(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define dump(x)
#endif

typedef long long int ll;
typedef pair<int,int> pii;
//template<typename T> using vec=std::vector<T>;

const int INF=1<<30;
const long long int INF_=1LL<<58;
const double EPS=1e-9;
const int dx[]={1,0,-1,0},dy[]={0,1,0,-1};

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec){
	os << "[";
	for (const auto &v : vec) {
		os << v << ",";
	}
	os << "]";
	return os;
}

void Solve(){
	int n,K;
	scanf("%d%d",&n,&K);

	vector<pair<double,double>> ps;
	const double PI=3.14159265359;
	rep(i,0,n){
		double x,y,r;
		scanf("%lf%lf%lf",&x,&y,&r);
		if(y+r<=0) continue;
		if(y-r<=0){
			double f,s;
			if(x<0){
				f=atan2(y,x)-asin(r/sqrt(x*x+y*y));
				s=PI;
			}else{
				f=0;
				s=atan2(y,x)+asin(r/sqrt(x*x+y*y));
			}
			while(f<0) f+=PI;
			while(s<0) s+=PI;
			ps.push_back(mp(f,s));
		}else ps.push_back(mp(atan2(y,x)-asin(r/sqrt(x*x+y*y)),atan2(y,x)+asin(r/sqrt(x*x+y*y))));
	}
	
	sort(ps.begin(),ps.end());
	ps.erase(unique(ps.begin(),ps.end()),ps.end());
	
	vector<pair<double,double>> tmp;
	rep(i,0,ps.size()){
		bool ok=true;
		rep(j,0,ps.size()){
			if(i==j) continue;
			if(ps[j].first<=ps[i].first&&ps[i].second<=ps[j].second){
				ok=false;
				break;
			}
		}
		if(ok) tmp.push_back(ps[i]);
	}
	ps=tmp;

	if(ps.size()==0){
		cout << 0 << endl;
		return;
	}

	vector<int> a(ps.size());
	rep(i,1,ps.size()){
		rep(j,0,i+1){
			if(ps[j].second>=ps[i].first){
				a[i]=j;
				break;
			}
		}
		if(a[i]==i) a[i]=i-1;
	}

	static double dp[1500][1501][2];
	dp[0][0][0]=0;
	dp[0][1][1]=ps[0].second-ps[0].first;
	double ans=dp[0][1][1];
	rep(i,1,ps.size()){
		rep(j,0,K+1){
			dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1]);
			if(j==0) continue;
			if(j==1) dp[i][j][1]=ps[i].second-ps[i].first;
			dp[i][j][1]=max(dp[a[i]][j-1][1]+ps[i].second-max(ps[i].first,ps[a[i]].second),dp[a[i]][j-1][0]+ps[i].second-ps[i].first);
			ans=max({ans,dp[i][j][1],dp[i][j][0]});
		}
	}

	printf("%.10lf\n",ans/PI);
}

int main(){
	Solve();
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 36584
final_rank: 5

code_snippet: #include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <utility>
#include <iomanip>
#include <algorithm>
#include <functional>
using namespace std;

typedef long long ll;
typedef vector<int> vint;
typedef vector<long long> vll;
typedef pair<int,int> pint;
typedef pair<long long, long long> pll;

#define MP make_pair
#define PB push_back
#define ALL(s) (s).begin(),(s).end()
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P) 
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P) 
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P) 
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P) 
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s; }



typedef double DD;

const DD INF = 1LL<<60;
const DD EPS = 1e-10;
const DD PI = acos(-1.0);
DD torad(int deg) {return (DD)(deg) * PI / 180;}
DD todeg(DD ang) {return ang * 180 / PI;}

struct Point {
    DD x, y;
    Point(DD x = 0.0, DD y = 0.0) : x(x), y(y) {}
    friend ostream& operator << (ostream &s, const Point &p) {return s << '(' << p.x << ", " << p.y << ')';}
};

Point operator + (const Point &p, const Point &q) {return Point(p.x + q.x, p.y + q.y);}
Point operator - (const Point &p, const Point &q) {return Point(p.x - q.x, p.y - q.y);}
Point operator * (const Point &p, DD a) {return Point(p.x * a, p.y * a);}
Point operator * (DD a, const Point &p) {return Point(a * p.x, a * p.y);}
Point operator * (const Point &p, const Point &q) {return Point(p.x * q.x - p.y * q.y, p.x * q.y + p.y * q.x);}
Point operator / (const Point &p, DD a) {return Point(p.x / a, p.y / a);}
Point conj(const Point &p) {return Point(p.x, -p.y);}
Point rot(const Point &p, DD ang) {return Point(cos(ang) * p.x - sin(ang) * p.y, sin(ang) * p.x + cos(ang) * p.y);}
Point rot90(const Point &p) {return Point(-p.y, p.x);}
DD cross(const Point &p, const Point &q) {return p.x * q.y - p.y * q.x;}
DD dot(const Point &p, const Point &q) {return p.x * q.x + p.y * q.y;}
DD norm(const Point &p) {return dot(p, p);}
DD abs(const Point &p) {return sqrt(dot(p, p));}
DD amp(const Point &p) {DD res = atan2(p.y, p.x); if (res < 0) res += PI*2; return res;}
bool eq(const Point &p, const Point &q) {return abs(p - q) < EPS;}
bool operator < (const Point &p, const Point &q) {return (abs(p.x - q.x) > EPS ? p.x < q.x : p.y < q.y);}
bool operator > (const Point &p, const Point &q) {return (abs(p.x - q.x) > EPS ? p.x > q.x : p.y > q.y);}
Point operator / (const Point &p, const Point &q) {return p * conj(q) / norm(q);}

int ccw(const Point &a, const Point &b, const Point &c) {
    if (cross(b-a, c-a) > EPS) return 1;
    if (cross(b-a, c-a) < -EPS) return -1;
    if (dot(b-a, c-a) < -EPS) return 2;
    if (norm(b-a) < norm(c-a) - EPS) return -2;
    return 0;
}

struct Line : vector<Point> {
    Line(Point a = Point(0.0, 0.0), Point b = Point(0.0, 0.0)) {
        this->push_back(a);
        this->push_back(b);
    }
    friend ostream& operator << (ostream &s, const Line &l) {return s << '{' << l[0] << ", " << l[1] << '}';}
};

struct Circle : Point {
    DD r;
    Circle(Point p = Point(0.0, 0.0), DD r = 0.0) : Point(p), r(r) {}
    friend ostream& operator << (ostream &s, const Circle &c) {return s << '(' << c.x << ", " << c.y << ", " << c.r << ')';}
};



vector<Point> tanline(Point p, Circle c) {
    vector<Point> res;
    DD d = norm(p - c);
    DD l = d - c.r * c.r;
    if (l < -EPS) return res;
    if (l <= 0.0) l = 0.0;
    Point cq = (p - c) * (c.r * c.r / d);
    Point qs = rot90((p - c) * (c.r * sqrt(l) / d));
    Point s1 = c + cq + qs, s2 = c + cq - qs;
    res.push_back(s1);
    res.push_back(s2);
    return res;
}



int N, K;
Circle cir[3100];
DD dp[2100][2100];

DD solve() {
    vector< pair<DD,DD> > inter;
    for (int i = 0; i < N; ++i) {
        if (abs(cir[i]) <= cir[i].r + EPS) return 1.0;
        
        vector<Point> ps = tanline(Point(0,0), cir[i]);
        DD left = amp(ps[0]), right = amp(ps[1]);
        if (left > right) left = 0;
        chmax(left, 0.0);
        chmin(right, PI);
        
        if (left < right) inter.PB(MP(right, left));
        //cout << i << " : " << cir[i] << ", " << amp(ps[0]) << ", " << amp(ps[1]) << " ; " << MP(left, right) << endl;
    }
    
    sort(ALL(inter));
    for (int i = 0; i < inter.size(); ++i) swap(inter[i].first, inter[i].second);
    for (int i = 0; i < inter.size(); ++i) {
        for (int j = i+1; j < inter.size(); ++j) {
            if (inter[j].first < inter[i].first) {
                inter.erase(inter.begin() + i--);
                break;
            }
        }
    }
    
    //COUT(inter);
    
    for (int i = 0; i < 2100; ++i) for (int j = 0; j < 2100; ++j) dp[i][j] = 0.0;
    DD res = 0.0;
    for (int i = 0; i < inter.size(); ++i) {
        int tmp = i;
        while (true) {
            if (inter[tmp].second <= inter[i].first) break;
            --tmp;
            if (tmp == -1) break;
        }
        for (int k = 0; k <= K; ++k) {
            chmax(dp[i+1][k], dp[i][k]);
            chmax(dp[i+1][k+1], dp[tmp+1][k] + inter[i].second - inter[i].first);
            chmax(dp[i+1][k+1], dp[tmp+2][k] + inter[i].second - inter[tmp+1].second);
            
            chmax(res, dp[i+1][k]);
        }
    }
    
    return res / PI;
}

int main() {
    //freopen( "/Users/macuser/Dropbox/Contest/input.in", "r", stdin );
    
    while (cin >> N >> K) {
        for (int i = 0; i < N; ++i) cin >> cir[i].x >> cir[i].y >>cir[i].r;
        cout << fixed << setprecision(9) << solve() << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 35960
final_rank: 4

code_snippet: #include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
double PI=3.14159265359;
int x[2000];
int y[2000];
int r[2000];
pair<double,double> p[2000];
pair<double,double> c[2000];
double dp[2000][2000];
int main(){
	int a,b;
	scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++){
		scanf("%d%d%d",x+i,y+i,r+i);
		double d=sqrt(x[i]*x[i]+y[i]*y[i]);
		double q=atan2(y[i],x[i]);
		if(q<-PI/2)q+=PI*2;
		double v=asin((double)r[i]/d);
		//printf("%f %f\n",(q-v)/PI*180,(q+v)/PI*180);
		p[i]=make_pair(max(0.0,min(PI,q-v)),min(PI,max(0.0,q+v)));
	}
	std::sort(p,p+a);
	int sz=0;
	for(int i=0;i<a;i++){
		bool ok=true;
		for(int j=0;j<a;j++){
			if(i!=j&&p[j].first<p[i].first&&p[i].second<p[j].second)ok=false;
		}
		if(ok){
			c[sz++]=p[i];
		}
	}
	double ret=0;
	for(int i=1;i<=b;i++){
		double tmp=0;
		int at=0;
		for(int j=0;j<sz;j++){
			while(c[at].second<c[j].first){tmp=max(tmp,dp[i-1][at]);at++;}
			dp[i][j]=max(tmp+c[j].second-c[j].first,dp[i-1][at]+c[j].second-c[at].second);
			ret=max(ret,dp[i][j]);
		}
	}printf("%.12f\n",ret/PI);
}
accuracy: 1
time_ms: 10
memory_kb: 25808
final_rank: 3