基礎演算法 - 二分與三分 - 蒟蒻複習基礎

来源:https://www.cnblogs.com/CIVAN-LXYAO/archive/2018/07/17/9326617.html
-Advertisement-
Play Games

二分是一種常用而且非常精妙的演算法,常常是我們解決問題的突破口。二分的基本用途是在單調序列或單調函數中做查找操作。因此,當問題的答案具有單調性時,就可以通過二分把求解轉化為判定(根據複雜度理論,判定的難度小於求解)。進一步的,我們還可以通過三分(適用於求解凸性函數)解決單峰函數的極值以及相關問題。 二 ...


  二分是一種常用而且非常精妙的演算法,常常是我們解決問題的突破口。二分的基本用途是在單調序列單調函數中做查找操作。因此,當問題的答案具有單調性時,就可以通過二分把求解轉化為判定(根據複雜度理論,判定的難度小於求解)。進一步的,我們還可以通過三分(適用於求解凸性函數)解決單峰函數的極值以及相關問題。

  • 二分

  思想:分而治之。將一個規模為n的問題分解為k個規模較小的子問題,這些子問題互相獨立且與原問題相同,(如果子問題的規模仍然不夠小,,再劃分為k個子問題),然後遞歸的求解這些子問題,最後用適當的方法將各個子問題的解合併成原問題的解。

  方法:a)二分查找:在一個單調有序的集合或函數中查找一個解,每次分為左右兩部分,判斷解在哪個區間(並調節上下界),並直到找到目標元素。

int binary_search(int x) {
    int l = 0, r = n;
    while (l < r) {
        int mid = (l + r) >> 1;
        if (a[mid] == x) {
            return mid;
        }
        if (a[mid] < x) {
            l = mid + 1;
        } else {
            r = mid;
        }
    }
    return - 1;
}

 

       b)二分答案:(最大值最小或最小值最大這類問題)這類雙最值問題常常選用二分法求解(二分之後,先假裝自己確定答案),配合貪心,DP等演算法,檢驗這個答案是否合理,將最優化問題轉化為判定性問題。

       c)代替三分:(對於單峰函數)二分導函數求函數極值。

  例題:Bzoj1734   Poj2018 ... ... 

  借書(2018沈陽集訓Day4 - 二分答案)

  題目描述

  Dilhao 一共有 n 本教科書,每本教科書都有一個難度值,他每次出題的時候都會從其中挑兩本教科書作為借鑒,如果這兩本書的難度相差越大,Dilhao 出的題就會越複雜,也就是說,一道題的複雜程度等於兩本書難度差的絕對值。   這次輪到 ldxxx 出題啦,他想要管 Dilhao 借 m 本書作為參考去出題,Dilhao 想知道,如果 ldxxx 在Dilhao給出的 m 本書里挑選難度相差最小的兩本書出題,那麼 ldxxx 出的題複雜程度最大是多少?

  輸入

   第一行是 n 和 m。    接下來的 n 行,每行一個整數 a[i] 表示第i本書的難度。     6 3
  5
  7
  1
  17
  13
  10

  輸出

   一個整數為 ldxxx 出的題複雜程度的最大值。     7     樣例解釋
  Dilhao給了ldxxx難度為1,10,17的三本書,ldxxx挑選難度為10和17的兩本書,出題複雜度為7;
  如果Dilhao給出其他任何三本書,其中的兩本書難度差的最小值都小於7,所以ldxxx出題的最大複雜程度為7。

  數據說明

  對於 30%的數據: 2<=n<=20; 
  對於 60%的數據: 2<=n<=1000; 
  對於 100%的數據: 2<=n<=100000, 2<=m<=n, 0<=ai<=1000000000。     題解:二分
// 二分答案
#include <iostream> #include <algorithm> using namespace std; long long diff[100010]; long long n, m, tmp, num_book; bool check (long long x) { num_book = 1; long long tmp = diff[1]; long long flag_one = 1; while (num_book < m) { long long next = tmp + x; long long flag = lower_bound(diff + flag_one, diff + n + 2, next) - diff; if (flag == n + 1) { return false; } num_book += 1; flag_one = flag; tmp = diff[flag]; } return true; } int main() { freopen("margin.in", "r", stdin); freopen("margin.out", "w", stdout); cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> diff[i]; } sort(diff + 1, diff + n + 1); long long l = 0; long long r = diff[n]; long long ans; diff[n + 1] = 2 * diff[n]; while (l <= r) { long long mid = (l + r) / 2; if (check(mid) == true) { ans = mid; l = mid + 1; } else if (check(mid) == false) { r = mid - 1; } } cout << ans << endl; return 0; }

 


 

  • 三分

  適用於凸性函數的極值問題(二次函數就是一個典型的單峰函數)。與二分法強調函數的單調性不同,三分法強調函數的單峰性。

適用函數

  在區間 [L,R] [L,R] 中找兩個三分點,也就是 mid 和 mmid,然後比較這兩個點的 y 值大小。如果是計算最大值的情況,那麼 y (mid) ≤ y (mmid),說明最大值肯定在 mid 右邊,這時把區間變成 [mid , R],反之變成 [L , mmid] ,直到 LL 和 RR 很接近為止。如果是求最小值的情況就反過來。

 

double cal() {
    double l = 0, r = pi / 2;
    while (r - l > eps) {
        double mid = (l + r) / 2;
        double mmid = (mid + r) / 2;
        if (f(mid) < f(mmid)) {
            l = mid;
        }
        else {
            r = mmid;
        }
    }
    return l;
}

 


 

  • 二分快速冪

  c/c++ 的 <math> 庫中有 pow 函數(pow(double a, double b)),但一般都是用來計算浮點數的,函數的時間複雜度是 O(b) 。有些時候,a,b 都是整數,且 b 比較大(1e8),我們肯定需要一些優化方法,那就是快速冪。

  快速冪有很多種寫法,但是結合二分的思想,無疑比遞歸要快很多。

  (先放個遞歸薛洋

// 遞歸
int
pw1(int x, int y, int p) { if (!y) { return 1; } int res = pw1(x, y / 2, p); res = res * res % p; if (y & 1) { res = res * x % p; } return res; }

 (再放個能治他的二分曉星塵

// 二分
int
pw2(int x, int y, int p) { int res = 1; while (y) { if (y & 1) { res = res * x % p; } y >>= 1; x = x * x % p; } return res; }

   皮這一下我很開心 Orz


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 01 基礎加強六天02 資料庫四天03 SQL和ADO三天04 JavaScript05 DOM06 JQuery07 .NET就業班-三層項目+SVN五天08 ASP.NET十一天09 圖書商城項目五天10 EF11 MVC兩天12 OA項目九天13 就業培訓14 win10APP開發15 Uni ...
  • Description 根據一些書上的記載,上帝的一次失敗的創世經歷是這樣的: 第一天, 上帝創造了一個世界的基本元素,稱做“元”。 第二天, 上帝創造了一個新的元素,稱作“α”。“α”被定義為“元”構成的集合。容易發現,一共有兩種不同的“α”。 第三天, 上帝又創造了一個新的元素,稱作“β”。“β ...
  • python3中str預設為Unicode的編碼格式 Unicode是一32位編碼格式,不適合用來傳輸和存儲,所以必須轉換成utf-8,gbk等等 所以在Python3中必須將str類型轉換成bytes類型的 在Python中使用encode的方式可以進行字元的編碼 實際用法: >>>a = "中國 ...
  • 半夜整理東西,發現一個以前沒留意到的小問題。 PHP 7.0+ 里支持了函數(和方法)的返回值類型提示,上述第二種寫法在解釋運行時會觸發一個 Fatal Error,要求返回值必須是 integer 類的一個實例: 當然,兩者在強制類型轉換時效果是一樣的: 相關鏈接 PHP difference b ...
  • 使用工具(可點擊下載) Microsoft HTML HELP javadoc2html 上述軟體基於Windows系統,javadoc2chm安裝過程中系統會檢測HTML HELP是否存在。簡單地下載安裝即可。 材料:jdk官方文檔 到oracle官網下載一個叫jdk-xuyyy-docs-all ...
  • Hibernate框架第一天 今天任務 教學導航 框架和CRM項目的整體介紹 Hibernate框架的學習路線 案例一:完成客戶的CRUD的操作 需求分析 技術分析之Hibernate框架的概述 Hibernate框架的概述 什麼是ORM(對象關係映射) Hibernate優點 技術分析之Hiber ...
  • 高階函數 概念 Scala混合了面向對象和函數式的特性,我們通常將可以作為參數傳遞到方法中的表達式叫做函數。在函數式編程語言中,函數是“頭等公民”,高階函數包含:作為值的函數、匿名函數、閉包、柯里化等等。 作為值的函數 可以像任何其他數據類型一樣被傳遞和操作的函數,每當你想要給演算法傳入具體動作時這個 ...
  • 安裝了go語言之後,還要設置路徑,如果不設置路徑,則執行 go 的時候會提示 go: command not found,提示的意思是沒有這個命令行。這個是因為還沒有設置PATH路徑。 設置路徑的方式是vi ~/.bash_profile,進去在首行添加一行 export PATH=$PATH:/u ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...