File tree Expand file tree Collapse file tree 3 files changed +90
-0
lines changed
Filter options
Expand file tree Collapse file tree 3 files changed +90
-0
lines changed
Original file line number Diff line number Diff line change
1
+ #pragma once
2
+ #include < bit>
3
+ #include < functional>
4
+ #include < numeric>
5
+
6
+ // Calculate next point to check in floating point "binary" search
7
+ double bisect_mid_fp (double a, double b) {
8
+ auto encode = [&](double x) -> unsigned long long {
9
+ auto tmp = std::bit_cast<unsigned long long >(x);
10
+ return x >= 0 ? (tmp ^ (1ULL << 63 )) : ~tmp;
11
+ };
12
+
13
+ auto decode = [&](unsigned long long x) -> double {
14
+ auto tmp = (x >> 63 ) ? (x ^ (1ULL << 63 )) : ~x;
15
+ return std::bit_cast<double >(tmp);
16
+ };
17
+
18
+ unsigned long long tmp = std::midpoint (encode (a), encode (b));
19
+
20
+ return decode (tmp);
21
+ }
22
+
23
+ // Binary search
24
+ // Maintain f(ok) = true and f(ng) = false and return (ok, ng)
25
+ // Final (ok, ng) satisfies |ok - ng| <= abs_tol
26
+ template <class T > auto bisect (T ok, T ng, const std::function<bool (T)> &f, T abs_tol = T()) {
27
+ struct Result {
28
+ T ok, ng;
29
+ };
30
+
31
+ while (true ) {
32
+ T mid = std::is_floating_point<T>::value ? bisect_mid_fp (ok, ng) : std::midpoint (ok, ng);
33
+ if (mid == ok or mid == ng) break ;
34
+ (f (mid) ? ok : ng) = mid;
35
+ if (ok - ng <= abs_tol and ng - ok <= abs_tol) break ;
36
+ }
37
+
38
+ return Result{ok, ng};
39
+ }
Original file line number Diff line number Diff line change
1
+ ---
2
+ title : Binary search (二分探索)
3
+ documentation_of : ./bisect.hpp
4
+ ---
5
+
6
+ 二分探索を行う.
7
+ 探索範囲が浮動小数点数で与えられた場合は, IEEE 754 の binary64 形式を 64 bit 整数だと思って上の桁から順に値を定めていくような挙動を示す(よって必ず 64 回以下のループで実行が完了する).
8
+
9
+ ## 使用方法
10
+
11
+ ### ` double bisect_mid_fp(double a, double b) `
12
+
13
+ 64 bit 浮動小数点数の区間に対する二分探索で,現在の探索範囲の両端の値をもとに次に探索すべき値を返す.
14
+ 引数 ` a ` や ` b ` は NaN でなければよい(非正規化数や無限でもよい).
15
+ 動作のイメージとして ` ok ` と ` ng ` がともに正の場合は幾何平均くらいのオーダーの値を返す.
16
+
17
+ ### ` template <class T> auto bisect(T ok, T ng, const std::function<bool(T)> &f, T abs_tol = T()) `
18
+
19
+ 二分探索を行い,条件を満たす値を求める関数.
20
+
21
+ - ` ok ` : ` f(x) == true ` を満たすことがわかっている ` x ` の値.
22
+ - ` ng ` : ` f(x) == false ` を満たすことがわかっている ` x ` の値.
23
+ - ` f ` : ` T ` 型の引数をとり,条件を満たす場合 ` true ` を返す判定関数.
24
+ - ` abs_tol ` : 許容絶対誤差. ` ok ` と ` ng ` の差がこの値以下になったら探索を打ち切る(デフォルトは ` T() ` ).
25
+ - 戻り値 : ` ok ` および ` ng ` の最終値を含む ` Result ` 構造体.
26
+
27
+ ## 問題例
28
+
29
+ - [ No.2352 Sharpened Knife in Fall - yukicoder] ( https://yukicoder.me/problems/no/2352 )
Original file line number Diff line number Diff line change
1
+ #define PROBLEM " https://yukicoder.me/problems/no/2352"
2
+ #define ERROR 1e-5
3
+ #include " ../bisect.hpp"
4
+
5
+ #include < cmath>
6
+ #include < iomanip>
7
+ #include < iostream>
8
+ using namespace std ;
9
+
10
+ int main () {
11
+ cin.tie (nullptr ), ios::sync_with_stdio (false ), cout << fixed << setprecision (10 );
12
+ int R, K;
13
+ cin >> R >> K;
14
+ const double pi = acos (-1 );
15
+
16
+ for (int i = 1 ; i < K + 1 ; ++i) {
17
+ double tgt = pi / (K + 1 ) * i;
18
+
19
+ auto res = bisect<double >(0 , pi , [&](double c) { return c - sin (c * 2 ) / 2 < tgt; });
20
+ cout << -cos (res.ng ) * R << ' \n ' ;
21
+ }
22
+ }
You can’t perform that action at this time.
0 commit comments