题目
给你一个下标从 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;
}
};
题目
给你一个下标从 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;
}
};
题目
假设你是一家合金制造公司的老板,你的公司使用多种金属来制造合金。现在共有 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:
输入:n = 3, k = 2, budget = 15, composition = [[1,1,1],[1,1,10]], stock = [0,0,100], cost = [1,2,3]
输出:5
解释:最优的方法是使用第 2 台机器来制造合金。
要想制造 5 份合金,我们需要购买:
输入:n = 2, k = 3, budget = 10, composition = [[2,1],[1,2],[1,1]], stock = [1,1], cost = [5,5]
输出:2
解释:最优的方法是使用第 3 台机器来制造合金。
要想制造 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;
}
};
题目
给你一个下标从 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());
}
};