LeetCode 363 期周赛

在这里插入图片描述

2859.计算 K 置位下标对应元素的和

题目

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。

请你用整数形式返回 nums 中的特定元素之 和 ,这些特定元素满足:其对应下标的二进制表示中恰存在 k 个置位。

整数的二进制表示中的 1 就是这个整数的 置位 。

例如,21 的二进制表示为 10101 ,其中有 3 个置位。

示例 1:

输入:nums = [5,10,1,5,2], k = 1
输出:13
解释:下标的二进制表示是:
0 = 0002
1 = 0012
2 = 0102
3 = 0112
4 = 1002 下标 1、2 和 4 在其二进制表示中都存在 k = 1 个置位。
因此,答案为 nums[1] + nums[2] + nums[4] = 13 。

示例 2:

输入:nums = [4,3,2,1], k = 2
输出:1
解释:下标的二进制表示是:
0 = 002
1 = 012
2 = 102
3 = 112
只有下标 3 的二进制表示中存在 k = 2 个置位。
因此,答案为 nums[3] = 1 。

思路

判断每个nums的下标有几个二进制1,如果个数等于k,那么加到sum中即可。

class Solution {
    
    
public:
   int countOnes(int num) {
    
    
       int count = 0;
       while (num != 0) {
    
    
           count += num & 1;
           num >>= 1;
       }   
       return count;
   }
   
   int sumIndicesWithKSetBits(vector<int>& nums, int k) {
    
    
       int len=nums.size();
       long long int sum=0;
       for(int i=0;i<len;++i){
    
    
           if(countOnes(i)==k){
    
    
               sum+=nums[i];
           }
       }
       return sum;
   }
};

2860.让所有学生保持开心的分组方法数

题目

给你一个下标从 0 开始、长度为 n 的整数数组 nums ,其中 n 是班级中学生的总数。班主任希望能够在让所有学生保持开心的情况下选出一组学生:
如果能够满足下述两个条件之一,则认为第 i 位学生将会保持开心:
这位学生被选中,并且被选中的学生人数 严格大于 nums[i] 。
这位学生没有被选中,并且被选中的学生人数 严格小于 nums[i] 。
返回能够满足让所有学生保持开心的分组方法的数目。

示例 1:

输入:nums = [1,1]
输出:2 解释:
有两种可行的方法:
班主任没有选中学生。
班主任选中所有学生形成一组。
如果班主任仅选中一个学生来完成分组,那么两个学生都无法保持开心。
因此,仅存在两种可行的方法。

示例 2:

输入:nums = [6,0,3,3,6,7,2,7]
输出:3
解释: 存在三种可行的方法:
班主任选中下标为 1 的学生形成一组。
班主任选中下标为 1、2、3、6 的学生形成一组。
班主任选中所有学生形成一组。

思路

首先,先按照升序进行排列。随后建立一个bool的数组,如果nums数组中包含的数,那么一定不可能是ans,跳过。

代码

class Solution {
    
    
public:
    int countWays(vector<int>& nums) {
    
    
        int len=nums.size();
        //升序排列
        sort(nums.begin(),nums.end());
        vector<bool> flage(len+5,true);
        
        //nums数组在包含的,不可能是要选的人数
        for(int i=0;i<len;++i){
    
    
            if(flage[nums[i]]){
    
    
                flage[nums[i]]=false;
            }
        }
        
        //遍历选0人和全选的情况
        int count=0,res=0;
        for(int i=0;i<=len;++i){
    
    
            if(!flage[i])
                continue;
            count=0;
            //遍历数组的每一个值
           auto it=upper_bound(nums.begin(), nums.end(), i);
           count=distance(nums.begin(), it);
            if(count==i)
                res++;
        }
        return res;
    }
};

2861.最大合金数

题目
假设你是一家合金制造公司的老板,你的公司使用多种金属来制造合金。现在共有 n 种不同类型的金属可以使用,并且你可以使用 k 台机器来制造合金。每台机器都需要特定数量的每种金属来创建合金。

对于第 i 台机器而言,创建合金需要 composition[i][j] 份 j 类型金属。最初,你拥有 stock[i] 份 i 类型金属,而每购入一份 i 类型金属需要花费 cost[i] 的金钱。

给你整数 n、k、budget,下标从 1 开始的二维数组 composition,两个下标从 1 开始的数组 stock 和 cost,请你在预算不超过 budget 金钱的前提下,最大化 公司制造合金的数量。

所有合金都需要由同一台机器制造。

返回公司可以制造的最大合金数。

示例 1:

输入:n = 3, k = 2, budget = 15, composition = [[1,1,1],[1,1,10]], stock = [0,0,0], cost = [1,2,3]
输出:2
解释:最优的方法是使用第 1 台机器来制造合金。
要想制造 2 份合金,我们需要购买:

  • 2 份第 1 类金属。
  • 2 份第 2 类金属。
  • 2 份第 3 类金属。
    总共需要 2 * 1 + 2 * 2 + 2 * 3 = 12 的金钱,小于等于预算 15 。
    注意,我们最开始时候没有任何一类金属,所以必须买齐所有需要的金属。
    可以证明在示例条件下最多可以制造 2 份合金。

示例 2:

输入:n = 3, k = 2, budget = 15, composition = [[1,1,1],[1,1,10]], stock = [0,0,100], cost = [1,2,3]
输出:5
解释:最优的方法是使用第 2 台机器来制造合金。
要想制造 5 份合金,我们需要购买:

  • 5 份第 1 类金属。
  • 5 份第 2 类金属。
  • 0 份第 3 类金属。
    总共需要 5 * 1 + 5 * 2 + 0 * 3 = 15 的金钱,小于等于预算 15 。
    可以证明在示例条件下最多可以制造 5 份合金。
    示例 3:

输入:n = 2, k = 3, budget = 10, composition = [[2,1],[1,2],[1,1]], stock = [1,1], cost = [5,5]
输出:2
解释:最优的方法是使用第 3 台机器来制造合金。
要想制造 2 份合金,我们需要购买:

  • 1 份第 1 类金属。
  • 1 份第 2 类金属。
    总共需要 1 * 5 + 1 * 5 = 10 的金钱,小于等于预算 10 。
    可以证明在示例条件下最多可以制造 2 份合金。

思路

假设要制造 num份合金,由于num越小花费的钱越少num 越多,花费的钱越多,有单调性,可以二分。

代码

class Solution {
    
    
public:
    int maxNumberOfAlloys(int n, int k, int budget, vector<vector<int>> &composition, vector<int> &stock, vector<int> &cost) {
    
    
        int ans = 0;
        int mx = *min_element(stock.begin(), stock.end()) + budget;
        for (auto &com: composition) {
    
    
            auto check = [&](long long num) -> bool {
    
    
                long long money = 0;
                for (int i = 0; i < n; i++) {
    
    
                    if (stock[i] < com[i] * num) {
    
    
                        money += (com[i] * num - stock[i]) * cost[i];
                        if (money > budget) {
    
    
                            return false;
                        }
                    }
                }
                return true;
            };
            int left = 0, right = mx + 1;
            while (left + 1 < right) {
    
     // 开区间写法
                int mid = (left + right) / 2;
                (check(mid) ? left : right) = mid;
            }
            ans = max(ans, left);
        }
        return ans;
    }
};

2862.完全子集的最大元素和

题目

给你一个下标从 1 开始、由 n 个整数组成的数组。

如果一组数字中每对元素的乘积都是一个完全平方数,则称这组数字是一个 完全集 。

下标集 {1, 2, …, n} 的子集可以表示为 {i1, i2, …, ik},我们定义对应该子集的 元素和 为 nums[i1] + nums[i2] + … + nums[ik] 。

返回下标集 {1, 2, …, n} 的 完全子集 所能取到的 最大元素和 。

完全平方数是指可以表示为一个整数和其自身相乘的数。

示例 1:

输入:nums = [8,7,3,5,7,2,4,9]
输出:16
解释:除了由单个下标组成的子集之外,还有两个下标集的完全子集:{1,4} 和 {2,8} 。
与下标 1 和 4 对应的元素和等于 nums[1] + nums[4] = 8 + 5 = 13 。
与下标 2 和 8 对应的元素和等于 nums[2] + nums[8] = 7 + 9 = 16 。
因此,下标集的完全子集可以取到的最大元素和为 16 。

示例 2:

输入:nums = [5,10,3,10,1,13,7,9,4]
输出:19
解释:除了由单个下标组成的子集之外,还有四个下标集的完全子集:{1,4}、{1,9}、{2,8}、{4,9} 和 {1,4,9} 。
与下标 1 和 4 对应的元素和等于 nums[1] + nums[4] = 5 + 10 = 15 。
与下标 1 和 9 对应的元素和等于 nums[1] + nums[9] = 5 + 4 = 9 。
与下标 2 和 8 对应的元素和等于 nums[2] + nums[8] = 10 + 9 = 19 。
与下标 4 和 9 对应的元素和等于 nums[4] + nums[9] = 10 + 4 = 14 。
与下标 1、4 和 9 对应的元素和等于 nums[1] + nums[4] + nums[9] = 5 + 10 + 4 = 19 。
因此,下标集的完全子集可以取到的最大元素和为 19 。

思路

根据题意,如果同一组中有两个数,它们的下标的 core\text{core}core 值不同,那么这两个数相乘,就不是一个完全平方数。
所以,同一组内的数字下标的 core\text{core}core 值必须都一样。 那么按照下标的 core\text{core}core
值分组,累加同一组的元素和,最大元素和即为答案。

代码

class Solution {
    
    
    int core(int n) {
    
    
        int res = 1;
        for (int i = 2; i * i <= n; i++) {
    
    
            int e = 0;
            while (n % i == 0) {
    
    
                e ^= 1;
                n /= i;
            }
            if (e) {
    
    
                res *= i;
            }
        }
        if (n > 1) {
    
    
            res *= n;
        }
        return res;
    }

public:
    long long maximumSum(vector<int> &nums) {
    
    
        vector<long long> sum(nums.size() + 1);
        for (int i = 0; i < nums.size(); i++) {
    
    
            sum[core(i + 1)] += nums[i];
        }
        return *max_element(sum.begin(), sum.end());
    }
};

猜你喜欢

转载自blog.csdn.net/m0_73731708/article/details/133000542