二分算法+acwing习题

文章介绍了二分算法在解决不同编程问题中的应用,包括寻找数的范围、数的三次方跟、机器人跳跃的最大步数、四平方和问题以及分巧克力问题。每个问题都提供了详细的代码实现,展示如何通过二分法找到答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分


整数二分步骤:
1.找一个区间[L,R],使得答案一定在该区间中。
2.找一个判断条件,使得该判断条件具有二段性,并且答案一定在该二段性的分界点。
3.分析终点M在该判断条件下是否成立,如果成立,考虑答案在哪个区间,如果不成立,考虑答案在那个区间。
4.如果更新方式写的是R = Mid,则不用做任何处理;如果更新方式写的是L = Mid,则需要在计算Mid时加上1。
在这里插入图片描述

1.数的范围789

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n, m;
int q[N];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);

    for (int i = 0; i < m; i ++ )
    {
        int x;
        scanf("%d", &x);
        // 二分x的左端点
        int l = 0, r = n - 1;   // 确定区间范围
        while (l < r)
        {
            int mid = l + r >> 1;//除2
            if (q[mid] >= x) r = mid;
            else l = mid + 1;
        }

        if (q[r] == x)
        {
            cout << r << ' ';

            // 二分x的右端点
            r = n - 1;  // 右端点一定在[左端点, n - 1] 之间
            while (l < r)
            {
                int mid = l + r + 1 >> 1;   // 因为写的是l = mid,所以需要补上1
                if (q[mid] <= x) l = mid;
                else r = mid - 1;
            }
            cout << r << endl;
        }
        else cout << "-1 -1" << endl;
    }

    return 0;
}
2.数的三次方跟790

在这里插入图片描述
在这里插入图片描述

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    double x;
    cin >> x;
    double l = -10000, r = 10000;
    while (r - l > 1e-8)
    {
        double mid = (l + r) / 2;
        if (mid * mid * mid >= x) r = mid;
        else l = mid;
    }

    printf("%lf\n", l);

    return 0;
}
3. 机器人跳跃问题730

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int num[N];
int n;
int main(){
    cin>>n;
    for(int i=0;i<n;i++)cin>>num[i];
    int res = 0;
        for(int i = n - 1; i >= 0; i--){
            if((num[i] + res) % 2 == 0)
                res = (num[i] + res) / 2;
            else
                res = (num[i] + res) / 2 + 1;
        }
    cout<<res<<endl;
}
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n;
int h[N];

bool check(int e)
{
    for (int i = 1; i <= n; i ++ )
    {
        e = e * 2 - h[i];
        if (e >= 1e5) return true;
        if (e < 0) return false;
    }
    return true;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &h[i]);

    int l = 0, r = 1e5;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }

    printf("%d\n", r);
	return 0;
}
4. 四平方和1221

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <cstring>    //暴力
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 2500010;

int n;

int main()
{
    cin >> n;
    for (int a = 0; a * a <= n; a ++ )
        for (int b = a; a * a + b * b <= n; b ++ )
            for (int c = b; a * a + b * b + c * c <= n; c ++ )
            {
                int t = n - a * a - b * b - c * c;
                int d = sqrt(t);
                if (d * d == t)
                {
                    printf("%d %d %d %d\n", a, b, c, d);
                    return 0;
                }
            }
}
#include <cstring>    //二分
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 2500010;

struct Sum
{
    int s, c, d;
    bool operator< (const Sum &t)const
    {
        if (s != t.s) return s < t.s;
        if (c != t.c) return c < t.c;
        return d < t.d;
    }
}sum[N];

int n, m;

int main()
{
    cin >> n;
    for (int c = 0; c * c <= n; c ++ )
        for (int d = c; c * c + d * d <= n; d ++ )
            sum[m ++ ] = {c * c + d * d, c, d};

    sort(sum, sum + m);

    for (int a = 0; a * a <= n; a ++ )
        for (int b = 0; a * a + b * b <= n; b ++ )
        {
            int t = n - a * a - b * b;
            int l = 0, r = m - 1;
            while (l < r)
            {
                int mid = l + r >> 1;
                if (sum[mid].s >= t) r = mid;
                else l = mid + 1;
            }
            if (sum[l].s == t)
            {
                printf("%d %d %d %d\n", a, b, sum[l].c, sum[l].d);
                return 0;
            }
        }

    return 0;
}
#include <cstring>   //哈希表
#include <iostream>
#include <algorithm>
#include <unordered_map>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 2500010;

int n, m;
unordered_map<int, PII> S;

int main()
{
    cin >> n;

    for (int c = 0; c * c <= n; c ++ )
        for (int d = c; c * c + d * d <= n; d ++ )
        {
            int t = c * c + d * d;
            if (S.count(t) == 0) S[t] = {c, d};
        }

    for (int a = 0; a * a <= n; a ++ )
        for (int b = 0; a * a + b * b <= n; b ++ )
        {
            int t = n - a * a - b * b;
            if (S.count(t))
            {
                printf("%d %d %d %d\n", a, b, S[t].x, S[t].y);
                return 0;
            }
        }

    return 0;
}
5.分巧克力1227

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n, k;
int h[N], w[N];//存储长、宽
bool check(int mid)
{
    int res = 0;//记录分成长度为 a 的巧克力数量
    for (int i = 0; i < n; i ++ )
    {
        res += (h[i] / mid) * (w[i] / mid);//每一大块可以分成的边长为 a 的巧克力数量
        if (res >= k) return true;//大于要求数量,返回真
    }

    return false;
}

int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i ++ ) scanf("%d%d", &h[i], &w[i]);

    int l = 1, r = 1e5;
    while (l < r)//二分小巧克力边长范围,找到符合要求的最大值
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }

    printf("%d\n", r);

    return 0;
}
### AcWing 算法基础课中的二分法相关练习题 #### 二分查找基本概念 二分查找是一种高效的搜索算法,适用于已排序的数据结构。其核心思想是在每次迭代中将搜索范围减半,从而快速定位目标值的位置[^1]。 #### 练习题推荐 ##### 查找特定元素 对于给定的一个升序数组`nums`以及一个整数值`target`,编写函数来实现二分查找返回该值首次出现位置;如果不存在则返回-1。 ```python def binary_search(nums, target): left, right = 0, len(nums) - 1 while left <= right: mid = (left + right) // 2 if nums[mid] == target and (mid == 0 or nums[mid - 1] != target): return mid elif nums[mid] >= target: right = mid - 1 else: left = mid + 1 return -1 ``` ##### 寻找峰值元素 在一个无重复元素的数组里找到任意一个满足条件`A[i]>A[i−1] && A[i]>A[i+1]` 的索引i作为峰顶并输出它; 如果有多个这样的点只需给出其中一个即可. ```cpp int findPeakElement(vector<int>& nums) { int n=nums.size(); if(n==1 || nums[0]>nums[1])return 0; if(nums[n-1]>nums[n-2])return n-1; int l=1,r=n-2; while(l<=r){ int m=(l+r)/2; if((m==n-1||nums[m]>nums[m+1])&&(m==0||nums[m]>nums[m-1]))return m; else if(m>0&&nums[m]<nums[m-1]) r=m-1; else l=m+1; } } ``` ##### 计算平方根 计算并返回非负实数x的小数部分最接近于y的那个数z(保留k位有效数字),其中y=x^(1/2). ```c++ double mySqrt(double x,int k) { double L = 0,R = max(1.0,x); for(int i=0;i<k;++i){ double M =(L+R)*0.5; if(M*M>x) R=M-(pow(10,-i)); else L=M+(pow(10,-i)); } return round(L*(pow(10,k)))/(pow(10,k)); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不掉发的小刘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值