二分算法+acwing习题

二分


整数二分步骤:
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;
}

猜你喜欢

转载自blog.csdn.net/YouWan797411/article/details/130692541