【力扣】中國銀聯專場周賽
中國銀聯專場
銀聯-03. 理財產品
某公司計劃推出一批投資專案。 product[i] = price
表示第 i
個理財專案的投資金額 price
。客戶在按需投資時,需要遵循以下規則:
- 客戶在首次對專案
product[i]
投資時,需要投入金額price
- 對已完成首次投資的專案
product[i]
可繼續追加投入,但追加投入的金額需小於上一次對該專案的投入(追加投入為大於0
的整數) - 為控制市場穩定,每人交易次數不得大於
limit
。(首次投資和追加投入均記作1
次交易)
若對所有理財專案中最多進行 limit
次交易,使得投入金額總和最大,請返回這個最大值的總和。
注意:
- 答案需要以
1e9 + 7 (1000000007)
1000000008
,請返回1
示例 1:
輸入:
product = [4,5,3], limit = 8
輸出:
26
解釋:滿足條件的一種情況為:
第一個理財專案進行金額為 4,3,2 的交易;
第二個理財專案進行金額為 5,4,3 的交易;
第三個理財專案進行金額為 3,2 的交易;
得到最大投入金額總和為 5 + 4 * 2 + 3 * 3 + 2 * 2 = 26。
示例 2:
輸入:
product = [2,1,3], limit = 20
輸出:
10
解釋:可交易總次數小於
limit
,因此進行所有交易
第一個理財專案可交易 2 次,交易的金額分別為 2,1;
第二個理財專案可交易 1 次,交易的金額分別為 1;
第三個理財專案可交易 3 次,交易的金額分別為 3,2,1;
因此所得最大投入金額總和為 3 + 2 * 2 + 1 * 3 = 10。
提示:
1 <= product.length <= 10^5
1 <= product[i] <= 10^7
1 <= limit <= 10^9
二分
我們把 p 看作不同高度的柱子,我們需要確定某個高度劃一刀,高的全選,少的從這個高度補。如果比這個高度低,那麼就會超過 limit 個。
class Solution: def maxInvestment(self, p: List[int], limit: int) -> int: # 二分上界和下界 a, b = 0, max(p) while a < b: mid = (a + b) // 2 # 高的高度 count = 0 for tmp in p: if tmp > mid: count += tmp - mid # 多了,不行 if count > limit: a = mid + 1 # 少了,行 else: b = mid print(b) ans, count = 0, 0 for tmp in p: if tmp > b: # 記錄個數 count += tmp - b # 高的全選,等差數列求和 ans += (tmp - b) * (b + 1 + tmp) // 2 # 不足的從這一層選 ans += b * (limit - count) return ans % 1000000007
銀聯-04. 合作開發
為了不斷提高使用者使用的體驗,開發團隊正在對產品進行全方位的開發和優化。
已知開發團隊共有若干名成員,skills[i]
表示第 i
名開發人員掌握技能列表。如果兩名成員各自擁有至少一門對方未擁有的技能,則這兩名成員可以「合作開發」。
請返回當前有多少對開發成員滿足「合作開發」的條件。由於答案可能很大,請你返回答案對 10^9 + 7
取餘的結果。
注意:
- 對於任意
skills[i]
均升序排列。
示例 1:
輸入:
skills = [[1,2,3],[3],[2,4]]
輸出:
2
解釋:
開發成員[1,2,3]
和成員[2,4]
滿足「合作開發」的條件,技能1
和4
分別是對方未擁有的技術
開發成員[3]
和成員[2,4]
滿足「合作開發」的條件,技能3
和4
分別是對方未擁有的技術
開發成員[1,2,3]
和成員[3]
不滿足「合作開發」的條件,由於開發成員[3]
沒有對方未擁有的技術
因此有2
對開發成員滿足「合作開發」的條件。
示例 2:
輸入:
skills = [[3],[6]]
輸出:
1
解釋:
開發成員[3]
和成員[6]
滿足「合作開發」的條件
因此有1
對開發成員滿足「合作開發」的條件。
提示:
2 <= skills.length <= 10^5
1 <= skills[i].length <= 4
1 <= skills[i][j] <= 1000
-
skills[i]
中不包含重複元素
逆向考慮 + 雜湊
假如 a 和 b 不能合作,而且 a 的技能比 b 多(或相等),那麼說明什麼, b 的技能 a 都有。那麼 a 的技能是 1 2 3 ,b 的技能就是 1,2,3 的子集。
class Solution:
def coopDevelop(self, skills: List[List[int]]) -> int:
# 排序後 a 不能合作的都在前面,後面也會有不能和 a 合作的
# 把這個看成有序方便討論
skills.sort(key=lambda x : len(x))
n = len(skills)
hash = defaultdict(int)
# 所有組合個數
ans = n * (n - 1) // 2
# print(skills)
# list is unhashable,tuple is hashable
hash[tuple(skills[0])] += 1
# 遍歷每個員工
for i in range(1, n):
# 得到所有子集
for j in range(len(skills[i])):
# combinations(skills[i], j + 1) skills[i] 中 j + 1 個元素的所有組合
for c in combinations(skills[i], j + 1):
ans -= hash[tuple(c)]
# 進入雜湊表
hash[tuple(skills[i])] += 1
return ans % 1_000_000_007
如果是 cpp 呢?怎麼搞?好在最多隻有 4 個 skill ,數值在 1 到 1000 ,也就是說一個 skill 可以用 10 bit 表示,最多需要 40 bit 。
class Solution {
unordered_map<long long, int> hash;
public:
int coopDevelop(vector<vector<int>>& skills) {
sort(skills.begin(), skills.end(), [&](vector<int> &a, vector<int> &b){return a.size() < b.size();});
int n = skills.size();
long long ans = n;
ans = ans * (n - 1) / 2;
long long s = 0;
for (int i = 0; i < n; i++) {
// 二進位制列舉,確定每個數選或者
for (int j = 1; j < 1 << skills[i].size(); j++) {
s = 0;
for (int k = 0; k < skills[i].size(); k++) {
if (((j >> k) & 1) == 1) {
s = (s << 10) + skills[i][k];
}
}
ans -= hash[s];
}
hash[s] += 1;
}
return ans % 1000000007;
}
};