dmkozyrev

559.cpp

May 12th, 2018
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.65 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. typedef long double Real;
  4.  
  5. const Real PI = std::acos(-1.0L);
  6. const Real EPS = 1e-14;
  7.  
  8. // Square of figure from 0 to x:
  9. Real square_till(Real r, Real d, Real x) {
  10.     if (x <= r) {
  11.         Real alpha = std::acos((r-x)/r);
  12.         return r * r * (alpha - std::sin(2 * alpha) / 2);
  13.     }
  14.     if (x >= r + d) {
  15.         return PI * r * r + d * 2 * r - square_till(r, d, 2 * r + d - x);
  16.     }
  17.     return PI * r * r / 2 + (x - r) * 2 * r;
  18. }
  19.  
  20. // Square of figure from x to y:
  21. Real square_before(Real r, Real d, Real x, Real y) {
  22.     return square_till(r, d, y) - square_till(r, d, x);
  23. }
  24.  
  25. // Find root of equation x = s / r^2 + sin(2*x) / 2 using binsearch:
  26. Real solve_binsearch(Real s, Real r) {
  27.     Real low = -100, high = 100;    
  28.     while (high - low > EPS) {
  29.         Real mid = (low + high) / 2;
  30.         Real value = mid - s / r / r - std::sin(2 * mid) / 2;
  31.         if (value >= 0) {
  32.             high = mid;
  33.         } else {
  34.             low = mid;
  35.         }
  36.     }
  37.     return (low + high) / 2;
  38. }
  39.  
  40. // Find root of equation x = s / r^2 + sin(2*x) / 2 using newton iterations
  41. Real solve_newton(Real s, Real r) {
  42.     // next = curr - f(curr) / f'(curr)
  43.     // f(x) = x - s / r^2 - sin(2*x) / 2
  44.     // f'(x) = 1 - cos(2*x)
  45.     Real curr = s / r / r + 0.5; // x0
  46.     while (true) {
  47.         Real next = curr - (curr - s / r / r - std::sin(2*curr) / 2) / (1 - std::cos(2*curr));
  48.         if (std::abs(next - curr) < EPS) {
  49.             break;
  50.         }
  51.         curr = next;
  52.     }
  53.     return curr;
  54. }
  55.  
  56. Real solve_equation(Real s, Real r) {
  57.     return solve_newton(s, r); // or solve_binsearch(s, r);
  58. }
  59.  
  60. // Get next from x = x1 point x2: square between x1 and x2 = s
  61. Real next(Real d, Real r, Real s, Real x1) {
  62.     if (square_before(r, d, x1, r) + EPS >= s) {
  63.         Real angle = solve_equation(square_till(r, d, x1) + s, r);
  64.         return r - std::cos(angle) * r;
  65.     }
  66.     if (square_before(r, d, x1, r + d) + EPS >= s) {
  67.         if (x1 <= r) {
  68.             return (s - PI * r * r / 2 + square_till(r, d, x1)) / (2 * r) + r;
  69.         } else {
  70.             return s / (2 * r) + x1;
  71.         }
  72.     }
  73.     if (square_before(r, d, x1, 2 * r + d) + EPS >= s) {
  74.         Real angle = solve_equation(PI * r * r / 2 - (s + square_before(r, d, r+d, x1)), r);
  75.         return r + d + r * std::cos(angle);
  76.     }
  77.     return -1;
  78. }
  79.  
  80. int main() {
  81.     Real d, r, n, x = 0;
  82.     std::cin >> d >> r >> n;
  83.     auto s = square_till(r, d, 2 * r + d) / n;
  84.     for (int i = 1; i < n; ++i) {
  85.         x = ::next(d, r, s, x);
  86.         assert(x != -1);
  87.         std::cout << std::fixed << std::setprecision(6) << x << "\n";
  88.     }
  89.     return 0;
  90. }
Advertisement
Add Comment
Please, Sign In to add comment