【算法笔记4.5小节-二分】二分

  1. 在一个严格递增序列A中找到给定的数x,输出其在数组中的下标。

    #include<stdio.h>
    #include<math.h>
    /*
    在一个严格递增序列A中找到给定的数x,输出其在数组中的下标。
    */
    int a[10]={3,7,8,11,15,21,33,52,66,88};;
    int binsearch(int left, int right, int x)
    {
         while(left<=right)
         {
            // int mid = (left+right)/2;   //有可能溢出
             int mid = left + (right - left)/2;  //替换
             if(a[mid]==x)
                return mid;
             if(a[mid]<x)
                left = mid+1;
             if(a[mid]>x)
                right =mid-1;
         }
         return -1;
    
    }
    int main()
    {
        int x = 11;
        int index = binsearch(0,9,x);
        printf("%d在数组a中的下标为%d\n",x, index);
    }
    

     

  2. 如果递增序列A中的元素可能重复,那么如何对给定的欲查询元素x,求出序列中第一个大于等于x的元素的位置L以及第一个大于x的元素的位置R,这样元素x在序列中的存在区间就是左闭右开区间[L,R)。

    #include<stdio.h>
    #include<math.h>
    /*
    如果递增序列A中的元素可能重复,那么如何对给定的欲查询元素x,求出序列中
    第一个大于等于x的元素的位置L以及第一个大于x的元素的位置R,这样
    元素x在序列中的存在区间就是左闭右开区间[L,R)
    */
    int a[10]={1,3,3,3,6};
    //第一问:求序列中的第一个大于等于x的元素的位置.
    int binsearch_1(int left, int right, int x)
    {
         while(left<right)  //对[left,right]来说,left==right意味着找到了唯一位置
         {
             int mid = left + (right - left)/2;  //取中间点
             if(a[mid]>=x)
                right = mid;
             if(a[mid]<x)
                left = mid+1;
         }
         return left;   //  返回夹住的位置
    }
    
    //求序列中第一个大于x的元素的位置
    int binsearch_2(int left, int right, int x)
    {
        while(left<right)  //对[left,right]来说,left==right意味着找到了唯一位置
         {
             int mid = left + (right - left)/2;  //取中间点
             if(a[mid]>x)
                right = mid;
             if(a[mid]<=x)  //不同点
                left = mid+1;
         }
         return left;
    }
    
    int main()
    {
        int x = 3;
        int l = binsearch_1(0,4,x);
        int r = binsearch_2(0,4,x);
        printf("[%d, %d]\n",l, r);
    }
    

     

  3. 计算\sqrt{}2 的近似值

    #include<stdio.h>
    const double eps = 1e-5;     //精度为10^(-5)
    double f(double x){         //计算f(x)
        return x*x;
    }
    double calSqrt()
    {
        double left=1, right=2, mid;    //[left,right]=[1,2]
        while(right - left > eps){
            mid = (left + right) / 2;
            if(f(mid)>2){
                right = mid;
            }
            else
                left = mid;
        }
        return mid;
    }
    
    int main()
    {
        printf("%.5lf\n",calSqrt());
    }
    
    //运行结果:1.41421
    

     

  4. 给定一个定义在[L,R]上的单调函数f(x),求f(x)=0的根。

    #include<stdio.h>
    /*
    给定一个定义在[L,R]上的单调函数f(x),求f(x)=0的根。
    假设函数f(x)在[L,R]上递增。
    */
    const double eps = 1e-5;     //精度为10^(-5)
    double f(double x){         //计算f(x)
        return x*x-2;
    }
    double solve(double L, double R)
    {
        double left=L, right=R, mid;    //[left,right]=[1,2]
        while(right - left > eps){
            mid = (left + right) / 2;
            if(f(mid)>0){
                right = mid;
            }
            else
                left = mid;
        }
        return mid; //所返回的当前mid值即为f(x)=0的根
    }
    
    int main()
    {
        printf("%.5lf\n",solve(1,2));
    }
    
    //运行结果:1.41421
    

     

  5. 装水问题:

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
/*
装水问题
*/
const double PI = acos(-1.0);
const double eps = 1e-5;     //精度为10^(-5)
double f(double R, double h){         //计算f(x)
    double alpha = 2*acos((R-h)/R);
    double L=2*sqrt(R*R-(R-h)*(R-h));
    double s1 = alpha*R*R/2 - L*(R-h)/2;
    double s2 = PI*R*R/2;
    return s1/s2;
}
double solve(double R, double r)
{
    double left=0, right=R, mid;    //[left,right]=[1,2]
    while(right - left > eps){
        mid = (left + right) / 2;
        double t = f(R,mid);
        if(t>r){
            right = mid;
        }
        else
            left = mid;
    }
    return mid; //所返回的当前mid值即为f(x)=0的根
}

int main()
{
    double R=10,r=0.5;

    printf("%.4f\n",solve(R,r));
}

//运行结果:1.41421

   6. 木棒切割问题: 给出N根木棒,长度均已知,现在希望通过切割它们来得到至少K段长度相等的木棒(长度必须是整数), 问这些长度相等的木棒最长能有多长。参考代码:https://blog.csdn.net/weixin_42717165/article/details/87161259

N = 3  K= 7

10 24 5

//运行结果 6

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
//木棒切割问题
int main()
{
    int N,K,a[3];
    scanf("%d%d",&N,&K);
    int right = 0;  //保存最大长度
    for(int i=0; i<N; i++)
    {
        scanf("%d",&a[i]);
        if(a[i]>right)
            right = a[i];
    }
    int left = 1;
    right++;
    //printf("%d\n",right);
    while(left+1<right) //(left,right] ,left+1==right 意味着唯一位置即最后的位置
    {
        int mid = (left+right)/2;
        int k=0;

        for(int i=0; i<N; i++)
            k+=a[i]/mid;

        if(k<K) right = mid;    //条件成立
        else left = mid;
    }
    printf("%d\n",right-1);
    return 0;
}

7 . 给出n个线段的长度,试将它们头尾(顺序任意)地组成一个凸多边形,使得凸多边形的外接圆的半径最大,求该最大半径。其中n不超过10^5,线段长度均不超过100.要求算法中不涉及坐标的计算。(待解决)

8. 快速幂

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
/*
求a^b%m,递归写法
*/
typedef long long LL;
LL binpow(LL a, LL b, LL m){
    if(b==0) return 1;  //如果b为0,那么a^0=1
    //b为奇数,转换为b-1
    //b&1 位与操作,判断b的末位是否为1
    if(b&1) return a*bin(a, b-1,m)%m;
    else{   //b为偶数,转换为b/2
        LL mul = binpow(a, b/2, m);
        return mul*mul%m;
    }
}

/*
求a^b%m,迭代写法
*/

LL binpow_1(LL a, LL b, LL m)
{
    LL ans=1;
    while( b > 0)
    {
        if(b & 1)
        {
             ans = ans * a % m;
        }
        a = a * a % m;//令a平方
        b >>= 1;    //右移,除2
    }
    return ans;
}
int main()
{
 
    return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值