• 二分法


    1. 二分查找法代码实现:

     1 // 二分查找法
     2 // A[]为严格递增序列,left为二分下界,x为欲查询的数
     3 // 二分区间为左闭右闭的[left, right], 传入的初值为[0, n-1]
     4 int binarySearch(int A[], int left, int right, int x){
     5     int mid;
     6     while (left <= right){
     7         mid = (left + right) / 2;  // mid = left + (right - left) / 2;
     8         if (A[mid] == x){
     9             return mid;
    10         }
    11         else if (A[mid] > x){
    12             right = mid - 1;
    13         }
    14         else if (A[mid] < x){
    15             left = mid + 1;
    16         }
    17     }
    18 
    19     return -1;
    20 }

    2. 二分法求序列中第一个大于等于x的元素的位置L

     1 // 求序列中第一个大于等于x的元素的位置L
     2 // 二分上下界为左闭右闭的[left, right], 传入的初值为[0, n]
     3 int lower_bound(int A[], int left, int right, int x){
     4     int mid;
     5     while (left < right){
     6         mid = (left + right) / 2;        
     7         if (A[mid] >= x){
     8             right = mid;
     9         }
    10         else{
    11             left = mid + 1;
    12         }
    13     }
    14     return left;            // 返回夹出来的位置
    15 }

    3. 二分法求序列中第一个大于x 的元素的位置R

     1 int upper_bound(int A[], int left, int right, int x){
     2     int mid;
     3     while (left < right){
     4         mid = (left + right) / 2;
     5         if (A[mid] > x){
     6             right = mid;
     7         }
     8         else{
     9             left = mid + 1;
    10         }
    11     }
    12     return left;
    13 }

    4. 二分法解决“寻找有序序列第一个满足某条件的元素的位置”问题的固定模板

     1 // 二分区间为左闭右闭[left, right], 初值必须能覆盖解的所有取值
     2 int solve(int left, int right){
     3     int mid;
     4     while (left < right){
     5         mid = (left + right) / 2;
     6         if (条件成立){
     7             right = mid;
     8         }
     9         else{
    10             left = mid + 1;
    11         }
    12     }
    13 
    14     return left;
    15 }

    5. 二分法求根号2的近似值

     1 double calSqrt(){
     2     double left = 1, right = 2, mid;        // [left, right] = [1, 2]
     3     while (right - left > eps){
     4         mid = (left + right) /2;
     5         if (f(mid) > 2){
     6             right = mid;
     7         }
     8         else{
     9             left = mid;
    10         }
    11     }
    12 
    13     return mid;
    14 }

    6. 二分法求某个单调函数根的近似值

     1 // 利用二分法求单调函数的根
     2 const double eps2 = 1e-5;
     3 double f(double x){
     4     return ...;            // 写函数的表达式
     5 }
     6 
     7 double solve(double L, double R){
     8     double left = L, right = R, mid;
     9     while (right - left > eps2){
    10         mid = (left + right) / 2;
    11         if (f(mid) > 0){
    12             right = mid;
    13         }
    14         else{
    15             left = mid;
    16         }
    17     }
    18     return mid;
    19 }            

    7. 快速幂的递归写法(二分法实现)

     1 // 快速幂的递归写法
     2 typedef long long LL;
     3 // a^b & m
     4 LL binaryPow(LL a, LL b, LL m){
     5     if (b == 0)
     6         return 1;
     7     if (b & 1){            // 如果b为奇数
     8         return a * binaryPow(a, b - 1, m) % m;
     9     }
    10     else{
    11         LL mu = binaryPow(a, b / 2, m);
    12         return mu * mu % m;
    13     }
    14 }

    二分使用实战:

            1030 完美数列 (25分)

    给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 Mmp,则称这个数列是完美数列。

    现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。

    输入格式:

    输入第一行给出两个正整数 N 和 p,其中 N(105​​)是输入的正整数的个数,p(109​​)是给定的参数。第二行给出 N 个正整数,每个数不超过 109​​。

    输出格式:

    在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。

    输入样例:

    10 8
    2 3 20 4 5 1 6 7 8 9
    
     

    输出样例:

    8

    分析:输入数据到数组,对数组进行排序,对每个元素用二分法求出第一个大于 a[i] * p 的元素的位置 j ,(j - i) 即为完美数列的长度,将所有长度取最大值即为结果

    代码:这里用到了上面求序列中第一个大于x 的元素的位置R的函数upper_bound()

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <math.h>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 long long a[100010] = { 0 };
     8 
     9 long long upper_bound(long long A[], long long left, long long right, long long x){
    10     long long mid;
    11     while (left < right){
    12         mid = (left + right) / 2;
    13         if (A[mid] > x){
    14             right = mid;
    15         }
    16         else{
    17             left = mid + 1;
    18         }
    19     }
    20     return left;
    21 }
    22 
    23 int main()
    24 {
    25     freopen("in.txt", "r", stdin);
    26     long long ans = 1;        //  存储“完美数列”的最大长度
    27     long long n, p;
    28     scanf("%lld %lld", &n, &p);
    29 
    30     // 读取输入
    31     for (long i = 0; i < n; i++){
    32         scanf("%lld", &a[i]);
    33     }
    34     // 排序
    35     sort(a, a + n);
    36     // 遍历数组,对每个元素都查找最大值的位置j,区间长度与ans比较,取较大者
    37     for (long long i = 0; i < n; i++){
    38         // 寻找第一个大于a[i] * p的元素的位置
    39         long long j = upper_bound(a, i + 1, n, a[i] * p);
    40         ans = max(ans, j - i);
    41     }
    42     printf("%lld
    ", ans);
    43     fclose(stdin);
    44     return 0;
    45 }
  • 相关阅读:
    -1.#IND000 &&图像类型转换
    三维点集拟合:平面拟合、RANSAC、ICP算法
    深度学习:又一次推动AI梦想(Marr理论、语义鸿沟、视觉神经网络、神经形态学)
    三维重建:Kinect几何映射-SDK景深数据处理
    《SLIC Superpixels》阅读笔记
    中国企业系列
    关于抠图的一些文章方法收集
    数学空间引论
    PCL:解决PCL和OpenCV冲突的方法
    游戏开发:OpenGL入门学习
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/12215149.html
Copyright © 2020-2023  润新知