【每日刷题】第2天
文章目录
- 1.Kotori和气球
- 2.主持人调度(二)
1.Kotori和气球
题目链接
解法:数学 - 排列组合
本题是n种气球(不限个数),m个位置
例子: 假设有6种气球,5个位置。
-
那么第一个位置有6种选法。
-
因为相同种类的气球不能相邻,我们又是从前往后安排每个位置选哪个气球,所以,我们只需要保证后一个位置气球种类和前一个位置气球的种类不相同即可。也就是第2个位置有5种选法(只需要和第一个位置的气球种类不相同),第3个位置、第4个位置和第5个位置都只有5种选法。
-
因为分步相乘,所以最终有6 * 5 * 5 * 5 * 5 种方案
经过上面这个例子,我们很容易可以总结出 如果是n种气球,m个位置,方案数=n 乘 (n - 1)的m-1次
注意: 不要忘记取模
C++代码实现:
#include <iostream>using namespace std;const int MOD = 109;int main()
{int n, m; cin >> n >> m;int ret = n;for(int i = 1; i <= m - 1; i++){ret = ret * (n - 1) % MOD;}cout << ret << endl;return 0;
}
2.主持人调度(二)
题目链接
题目分析
我们之前做过 “主持人调度”这道题,这道题是让我们判断一个主持人是否能主持全部活动。我们当时的思路是先将所有活动区间按照区间的左端点按从小到大排序,排序后,判断区间是否相交,只需要判断前一个区间的左端点是否大于等于后一个区间的右端点。
本题是让我们求举办n个活动,最少需要多少主持人。
所以我们的目标就是将所有的活动区间分给若干个主持人,每一个主持人主持的活动的区间都是两两不相交的,最后返回主持人的个数
思路分析:
-
把区间按照左端点按从小到大排序
-
按照顺序依次处理没有分配的区间,然后看看该区间能否放在已经处理好的区间的后面即可(其实就是判断这两个区间是否相交),如果可以放在多个已经处理好的区间的后面,随便选一个即可。
-
当一个主持人主持的活动大于1个的时候,我们仅需保存最新的活动,因为我们区间是已经排好序了的
但是,按照我们现在这个思路解答,时间复杂度是O(N^2)的,会超时。
优化:
因为我们每次只需要让新来的区间的左端点和已处理的区间的右端点比较,所以,对于已处理的区间,我们只用存它的右端点,然后看新来的区间的左端点是否大于这个数。
其实,我们只需要让新来的区间的左端点和所有已处理区间中右端点的最小值比较即可。
所以,我们存已处理的区间的右端点的时候,可以存到小根堆里面,这样的话,堆顶就是最小的,如果新来的区间的左端点大于堆顶元素的值,那么就更新堆顶元素的值,如果小于等于堆顶的值,那么就让这个新区间的右端点进堆
注意:
如果一个区间的右端点等于另一个区间的左端点的这种情况,是算作两个区间没有重叠的
C++代码实现:
class Solution {
public:int minmumNumberOfHost(int n, vector<vector<int> >& startEnd) {sort(startEnd.begin(), startEnd.end());priority_queue<int, vector<int>, greater<int>> heap;//创建一个小根堆heap.push(startEnd[0][1]); // 第一个主持人for(int i = 1; i < n; i++){int left = startEnd[i][0]; int right = startEnd[i][1];if(left >= heap.top()) //区间没有重叠,同一个主持人主持{//更新堆顶元素heap.pop();heap.push(right);}else //区间重叠了,需要再来一个主持人 {heap.push(right);}}return heap.size();}
};