【备战秋招】每日一题:2023.05.15-拼多多OD机试(第二题)-多多的植树计划IV

news/2024/7/20 16:15:33 标签: 算法, 华为od, 华为, python, java

为了更好的阅读体检,可以查看我的算法学习博客
在线评测链接:P1297

题目描述

塔子哥安排你去他的养鸡场干活,养鸡场的名字是一串神秘代码—— C r a z y 4 Crazy 4 Crazy4

塔子哥的养鸡场里养了 N N N 只鸡(编号 1   N 1~N 1 N)。

由于塔子哥从“开封菜”引入了全自动养鸡系统,所以你要学会使用这个系统,它使用一个素质值来全方位描述每只鸡的生长情况。在这个系统里,编号为 i i i 的鸡有一个素质值 H i H_i Hi

你需要操控系统给鸡补充食物,每次给某只鸡投喂食物可以使其素质值上升 A A A ;同时由于所有的鸡都是散养的,你直接给某只鸡投喂食物,也会间接给其他所有鸡投喂食物,所以其他鸡的素质值也会同时上升 B B B 点( B ≤ A B \leq A BA )。为了这些鸡都能够顺利成长,好及时投入市场,塔子哥希望所有的鸡的素质值都要不小于 M M M

现在塔子哥想知道,在达到这个目标的前提下,最少的投喂次数是多少。

输入描述

输入第一行四个整数 N , M , A , B N,M,A,B NMAB ,分别表示鸡的数量、目标素质值、直接喂食增加的素质值、间接喂食增加的素质值。( 1 ≤ N 1 \leq N 1N, M , A , B M,A,B M,A,B ≤ 1 0 6 \leq 10^6 106 B ≤ A B \leq A BA )

接下来 N N N 行,每行一个整数 H i H_i Hi,分别表示第 i i i 只鸡初始的素质值 H _ i H\_i H_i 。( 0 ≤ H i ≤ 1 0 6 0 \leq H_i \leq 10^6 0Hi106 )

输出描述

输出共一行一个整数,表示达到目标最少的喂食次数。

样例

输入

5 8 4 2
0
2
4
6
8

输出

3

样例说明

可能的一种方案为:
第一次喂食选择第1只鸡,素质变为:{4,4,6,8,10}
第二次喂食选择第1只鸡,素质变为:{8,6,8,10,12}
第三次喂食选择第1只鸡,素质变为:{12,8,10,12,14}
满足所有鸡的素质都不小于8

样例2

输入

4 10 4 4
2
2
2
2

输出

2

思路:二分答案

对于二分答案这种题目,我们先考虑如何思考得到这种解法。

首先考虑投喂次数为 c n t cnt cnt ,那么每只鸡素质值上升 c n t × B cnt\times B cnt×B。再考虑这 c n t cnt cnt 次投喂的每次投喂会给哪只鸡。此时每只鸡的素质为 H i + c n t × B H_i+cnt\times B Hi+cnt×B。 当 H i + c n t × B < M H_i+cnt\times B < M Hi+cnt×B<M,则 c n t cnt cnt 次投喂中,需要给第 i i i 只鸡投喂一定的次数,使得其素质 ≥ M \geq M M,这个次数为 ⌊ M − ( H i + c n t × B ) A − B ⌋ \lfloor \frac{M - (H_i+cnt\times B)}{A-B}\rfloor ABM(Hi+cnt×B),注意,这里的 A > B A>B A>B 才有效,从实际意义来看,如果 A = B A=B A=B ,则投喂给哪只鸡都是一样的,所以这里的指定投喂指的是对于 A > B A>B A>B 的情况。

但是,当 c n t cnt cnt 次投喂不能使得所有鸡的素质都 ≥ M \geq M M 时,就需要提高投喂次数,但是如果说每次投喂次数 + 1 +1 +1 这样去继续判断,一次 c h e c k check check O ( n ) O(n) O(n) 的,再加上 O ( n ) O(n) O(n) 次投喂次数的选择, O ( n 2 ) O(n^2) O(n2) 则必然是超时的。

c n t cnt cnt 次投喂不能满足要求,那么 c n t − 1 cnt - 1 cnt1 次投喂必然也不能满足要求,但是 c n t + 1 cnt + 1 cnt+1 次投喂可能会满足要求。那么这个问题就具有了二段性,存在某一个数 m i d mid mid ,当投喂次数大于等于 m i d mid mid,则可以满足要求,当投喂次数小于 m i d mid mid ,则必然不可以满足要求。故我们二分答案,即二分投喂次数,每次 c h e c k check check 一下是否可以满足要求即可。

时间复杂度: O ( n log ⁡ max ⁡ ( h i ) ) O(n\log \max(h_i)) O(nlogmax(hi))

类似题目推荐

学习教程:Codefun2000 二分答案入门教程

代码

CPP

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

int n, m, A, B;
int h[1000000];
bool check(long long mid) {
    int extra = A - B;
    // mid次投喂后,每只鸡至少增加 mid*B
    long long cur = mid * B;
    for (int i = 0; i < n; ++i) {
        // ch 表示第 i 只鸡的素质还需要提升 ch 才能大于等于 M
        long long ch = m - cur - h[i];
        if (ch > 0) {
            // 注意,当 A > B 才能增加额外的素质,否则 A - B = 0,除法不能除 0
            if (A > B) {
                mid -= (ch + extra - 1) / extra;
                // 如果投喂次数超过 mid ,则说明 mid 次不够
                if (mid < 0) return false;
            } else {
                // 如果 A = B,但是这只鸡还需要增加素质,则 mid 次投喂不够
                return false;
            }
        }
    }
    // 如果所有鸡都满足条件,则返回 true
    return true;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> m >> A >> B;

    for (int i = 0; i < n; i++) {
        cin >> h[i];
    }

    // 二分答案,M 最多为 1e6,且最多有1e6只鸡,故最多1e12次投喂
    long long l = 0, r = 1e12;
    while (l < r) {
        long long mid = (l + r) / 2;
        if (check(mid)) {
            r = mid;
        } else {
            l = mid + 1;
        }
    }
    cout << l << "\n";
    return 0;
}

python_152">python

python">n, m, A, B = map(int, input().split())
extra = A - B

h = [0] * n
for i in range(n):
    h[i] = int(input())


def check(mid):
    global m, B, extra
    # mid次投喂后,每只鸡至少增加 mid*B
    cur = mid * B
    i = 0
    while i < n:
        # ch 表示第 i 只鸡的素质还需要提升 ch 才能大于等于 M
        ch = m - cur - h[i]
        if ch > 0:
            # 注意,当 A > B 才能增加额外的素质,否则 A - B = 0,除法不能除 0
            if A > B:
                mid -= (ch + extra - 1) // extra
                # 如果投喂次数超过 mid ,则说明 mid 次不够
                if mid < 0:
                    return False
            else:
                # 如果 A = B,但是这只鸡还需要增加素质,则 mid 次投喂不够
                return False

        i += 1

    # 如果
    return True


# 二分答案,M 最多为 1e6,且最多有1e6只鸡,故最多1e12次投喂
l, r = 0, int(1e12)
while l < r:
    mid = (l + r) // 2
    if check(mid):
        r = mid
    else:
        l = mid + 1

print(l)

Java

java">import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int A = sc.nextInt();
        int B = sc.nextInt();
        // 读入每只鸡的素质值
        int[] h = new int[n];
        for (int i = 0; i < n; i++) {
            h[i] = sc.nextInt();
        }

        // 二分答案,M 最多为 1e6,且最多有1e6只鸡,故最多1e12次投喂
        long l = 0, r = (long) 1e12;
        while (l < r) {
            long mid = (l + r) / 2;
            if (check(mid, h, m, A, B)) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }

        // 输出结果
        System.out.println(l);
    }

    // 检查是否满足条件
    public static boolean check(long mid, int[] h, int m, int A, int B) {
        int extra = A - B;
        // mid次投喂后,每只鸡至少增加 mid*B
        long cur = mid * B;
        for (int i = 0; i < h.length; ++i) {
            // ch 表示第 i 只鸡的素质还需要提升 ch 才能大于等于 M
            long ch = m - cur - h[i];
            if (ch > 0) {
                // 注意,当 A > B 才能增加额外的素质,否则 A - B = 0,除法不能除 0
                if (A > B) {
                    mid -= (ch + extra - 1) / extra;
                    if (mid < 0) return false;
                } else {
                    return false;
                }
            }
        }
        return true;
    }
}

Go

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	in := bufio.NewReader(os.Stdin)

	var n, m, A, B int
	fmt.Fscan(in, &n, &m, &A, &B)
	// 读入每只鸡的素质值
	h := make([]int, n)
	for i := 0; i < n; i++ {
		fmt.Fscan(in, &h[i])
	}

	// 二分答案,M 最多为 1e6,且最多有1e6只鸡,故最多1e12次投喂
	var l, r int64 = 0, 1e12
	for l < r {
		mid := (l + r) / 2
		if check(mid, h, m, A, B) {
			r = mid
		} else {
			l = mid + 1
		}
	}

	// 输出结果
	fmt.Println(l)

}

// 检查是否满足条件
func check(mid int64, h []int, m, A, B int) bool {
	extra := A - B
	// mid次投喂后,每只鸡至少增加 mid*B
	cur := mid * int64(B)
	for i := 0; i < len(h); i++ {
		// ch 表示第 i 只鸡的素质还需要提升 ch 才能大于等于 M
		ch := int64(m) - cur - int64(h[i])
		if ch > 0 {
			// 注意,当 A > B 才能增加额外的素质,否则 A - B = 0,除法不能除 0
			if A > B {
				mid -= (ch + int64(extra) - 1) / int64(extra)
				if mid < 0 {
					return false
				}
			} else {
				return false
			}
		}
	}
	return true
}

Js

process.stdin.resume();
process.stdin.setEncoding('utf-8');
let input = '';
process.stdin.on('data', (data) => {
    input += data;
    return;
});
process.stdin.on('end', () => {
    const lines = input.trim().split('\n');

    // 读入 n,m,A,B 四个整数
    const [n, m, A, B] = lines[0].trim().split(' ').map(Number);

    // 读入每只鸡的素质值
    const h = [];
    for (let i = 0; i < n; i++) {
        h.push(parseInt(lines[i + 1]));
    }

    // 二分答案,M 最多为 1e6,且最多有1e6只鸡,故最多1e12次投喂
    let l = 0, r = 1e12;
    while (l < r) {
        const mid = Math.floor((l + r) / 2);
        if (check(mid, h, m, A, B)) {
            r = mid;
        } else {
            l = mid + 1;
        }
    }

    // 输出结果
    console.log(l);
});

// 检查是否满足条件
function check(mid, h, m, A, B) {
    const extra = A - B;
    // mid次投喂后,每只鸡至少增加 mid*B
    let cur = mid * B;
    for (let i = 0; i < h.length; i++) {
        // ch 表示第 i 只鸡的素质还需要提升 ch 才能大于等于 M
        const ch = m - cur - h[i];
        if (ch > 0) {
            // 注意,当 A > B 才能增加额外的素质,否则 A - B = 0,除法不能除 0
            if (A > B) {
                mid -= Math.ceil(ch / extra);
                if (mid < 0) {
                    return false;
                }
            } else {
                return false;
            }
        }
    }
    return true;
}

题目内容均收集自互联网,如如若此项内容侵犯了原著者的合法权益,可联系我: (CSDN网站注册用户名: 塔子哥学算法) 进行删除。


http://www.niftyadmin.cn/n/1010453.html

相关文章

gcc编译过程详解

以一个简单的C代码为例&#xff0c;详细讲解gcc整个编译过程。 1、预处理 主要处理#开头的东西&#xff0c;例如头文件处理、条件编译处理、将宏定义进行替换&#xff0c;还可以去掉注释、添加行号等。预处理的命令如下&#xff1a; gcc -E hello.c -o hello.i #-E表示预处理…

IDEA 设置文件头的注释信息author,date,description

打开setting设置窗口 file and code Templates 2、编辑Class模版 /*** Author:${USER}* Date:${YEAR}-${MONTH}-${DAY}* Description:TODO* */ 创建一个新JAVA类&#xff0c;测试一下&#xff0c;OK

Elasticsearch同义词自定义词库未生效原因

检查文件及目录是否存在所有节点配置完之后都要重启检查测试脚本是否正确的,我遇到的问题就是脚本不正确但是确能执行,就是拿不到正确结果 错误脚本: PUT test_idx_analyzer3 {"settings": {// 这里是分析器 不是分词器; 分词器可以包含设置过滤器和分词器"an…

零信任:基于Apisix构建认证网关

背景 零信任一直是我们未来主攻的一个方向&#xff0c;全球加速&#xff0c;SD-WAN组网都是一些非常成熟的产品&#xff0c;全球加速是我们所有产品的底座&#xff0c;SD-WAN解决的是多个网络打通的问题&#xff0c;而零信任则主打应用访问。 关于零信任&#xff0c;我们已经…

预约Oracle OCP认证考试的保姆式流程

Oracle OCP认证考试的预约流程涉及到Oracle的SLS培训记录&#xff0c;因此相当复杂。本文进行了详细地说明&#xff0c;每一步都有截图&#xff0c;有需要的同学建议收藏。 关于号主&#xff0c;姚远 Oracle ACE&#xff08;Oracle和MySQL数据库方向&#xff09;。Oracle MAA…

High Performance Visual Tracking with Siamese Region Proposal Network(SiamRPN)

High Performance Visual Tracking with Siamese Region Proposal Network&#xff08;SiamRPN&#xff0c;CVPR2018&#xff09; 主要贡献&#xff1a; 提出了SiamRPN跟踪器&#xff0c;首次将端到端的离线训练方式&#xff0c;应用到了大尺度的图像跟踪任务上在在线跟踪过程…

Spring Boot 中的 @HystrixCommand 注解

Spring Boot 中的 HystrixCommand 注解 简介 在分布式系统中&#xff0c;服务之间的调用是不可避免的。但随着服务数量的增加&#xff0c;服务之间的依赖关系也会变得越来越复杂&#xff0c;服务的故障也会变得越来越常见。一旦某个服务出现故障&#xff0c;它所依赖的服务也…

我在「亚马逊云科技中国峰会」做讲师 - 「程序员的社区成长史」

文章目录 ⭐️ Part - 〇&#xff1a;开场的自我介绍⭐️ Part - ①&#xff1a;程序员的学习从技术社区开始&#x1f31f; 编程初学者共同面对的迷茫&#x1f31f; 加入一个适合自己的技术社区&#x1f31f; 反哺社区做有价值的贡献者 ⭐️ Part - ②&#xff1a;与技术社区的…