🔔目录
蓝桥杯冲冲冲~
回顾
🔖蓝桥杯每日练习(猴子分香蕉,等差数列,平方序列,倍数问题)
🔖蓝桥杯每日练习(纯质数(筛法的应用),最少砝码,灌溉)
🔖蓝桥杯每日练习(年龄巧合,纸牌三角形,取球游戏)
🚀今日题目
💓巧排扑克牌
栈模拟 |
题目描述
小明刚上小学,学会了第一个扑克牌“魔术”,到处给人表演。魔术的内容是这样的:
他手里握着一叠扑克牌:A,2,…J,Q,K一共 13张。他先自己精心设计它们的顺序,然后正面朝下拿着,开始表演。
只见他先从最下面拿一张放到最上面,再从最下面拿一张翻开放桌子上,是 A;然后再从最下面拿一张放到最上面,再从最下面拿一张翻开放桌子上,是 2;…如此循环直到手中只有一张牌,翻开放桌子上,刚好是 K。
这时,桌上牌的顺序是:A,2,3,4,5,6,7,8,9,10,J,Q,K。
请你计算一下,小明最开始的时候手里牌的顺序是怎样的。
把结果写出来,逗号分割,小明“魔术”开始时,最下面的那张牌输出为第一个数据。
原题传送门
解题报告
因为他是填空题,所以我们可以直接手算。具体怎么算呢,我们读题之后抽出有用的信息,可以知道他的放牌方式是隔一张放一张,所以我们就可以模拟了。
第一次直接排到最后:x1x2x3x4x5x6x(x表示空的位置),那么表示我们接下来可以用的位置是第1,3,5,7,9,11,13,所以第二次就直接隔一个来填充空位,以此类推直到填充完13个位置。每次找空位置的方法,其实就是数据结构中的栈。
参考代码(C++版本)
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout<<"7, A, Q, 2, 8, 3, J, 4, 9, 5, K, 6, 10";
return 0;
}
🌟质数拆分
🌱题目描述
将 2019 拆分为若干个两两不同的质数之和,一共有多少种不同的方法?
注意交换顺序视为同一种方法,例如 2 + 2017 = 2019 与 2017 + 2 = 2019视为同一种方法。
原题传送门
🌴解题报告
先用各种筛法把1~2019之间的素数筛出来(当然用什么筛法都可以),然后问题就转化成了一个01背包。对于每一个素数我们要考虑的是放与不放,计算出能加到每一个数字的方案数。我们用dp[i]来表示和是i的方案数,加上不放当前素数的方案数来转移,就可以求出答案。就得要初始化dp[0]=1(什么也不放就能达到0)。
🌵参考代码(C++版本)
#include <iostream>
using namespace std;
#define int long long
const int N=2020;
int primes[N];
int idx;
int st[N];
int d[N];
void prime() {
for(int i=2;i<=2019;i++) {
if(!st[i]) primes[idx++]=i;
for(int j=0;j<idx&&primes[j]*i<=2019;j++) {
st[primes[j]*i]=1;
if(i%primes[j]==0) break;
}
}
}
signed main()
{
prime();
d[0]=1;
for(int i=0;i<idx;i++) {
for(int j=2019;j>=primes[i];j--) {
d[j]+=d[j-primes[i]];
}
}
cout<<d[2019];
return 0;
}
日志统计
题目描述
小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有 N 行。其中每一行的格式是:
ts id
表示在 ts 时刻编号 id 的帖子收到一个"赞"。
现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为 D 的时间段内收到不少于 K 个赞,小明就认为这个帖子曾是"热帖"。
具体来说,如果存在某个时刻 T 满足该帖在 [T,T+D) 这段时间内(注意是左闭右开区间)收到不少于 K 个赞,该帖就曾是"热帖"。
给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。
原题传送门
🚗解题报告
每一个事件(称关于点赞的描述为事件)都是属于一个人的,所以我们可以按照每个人的编号把事件进行分类。分属到每个人后我们排序就可以得到按照时间顺序的描述了。我们枚举每个人的编号,然后枚举属于他的事件中k个为一组,看每组的时间差是不是在d以内。如果满足条件,我们就可以直接输出编号,开始对下一个人的检查。这样做乍一看两层循环时间复杂度是 n 2 n^2 n2的,但是仔细一想就会发现一个事件只会属于一个人,所以每一个事件最多只会被遍历到一次。
参考代码(C++版本)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
vector<int>res[N];
int n, d, k;
int main()
{
cin >> n >> d >> k;
for (int i = 0; i < n; i++) {
int a, b;
cin >> a >> b;
res[b].push_back(a);
}
for(int i = 0;i < N; i++) sort(res[i].begin(),res[i].end());
for (int i = 0; i < N; i++) {
if (res[i].size()<k) continue;
for (int j = 0; j < res[i].size() - k + 1; j++) {
int end = j + k - 1;
if (res[i][end] - res[i][j] < d) {
cout << i << endl;
break;
}
}
}
return 0;
}
递增三元组
题目描述
给定三个整数数组
A = [A1, A2, … AN],
B = [B1, B2, … BN],
C = [C1, C2, … CN],
请你统计有多少个三元组(i, j, k) 满足:
1. 1 <= i, j, k <= N
2. Ai < Bj < Ck
原题传送门
解题报告
要使三个数满足 Ai < Bj < Ck,我们只需要枚举第二个数字x,找到第一个数组中比x小的数的数量a,和第三个数组中比x大的数的数量b,然后用a*b就是x能得到的三元组的数组。找的过程我们可以先排序,然后用二分查找的方式来找到对应位置。
参考代码(C++版本)
#include <iostream>
#include <vector>
#include <algorithm>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N], c[N];
int n;
signed main()
{
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < n; i++) cin >> b[i];
for (int i = 0; i < n; i++) cin >> c[i];
sort(a, a + n), sort(b, b + n), sort(c, c + n);
int ans = 0;
for (int i = 0; i < n; i++) {
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r + 1>> 1;
if (a[mid] < b[i]) l = mid;
else r = mid - 1;
}
int first = r;
if (a[first] >= b[i]) continue;
l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (c[mid] > b[i]) r = mid;
else l = mid + 1;
}
int second = r;
if (c[second] <= b[i]) continue;
ans += (first + 1) * (n - second);
}
cout << ans << endl;
return 0;
}
外卖店优先级
题目描述
"饱了么"外卖系统中维护着 N 家外卖店,编号 1 ∼ N。每家外卖店都有 一个优先级,初始时 (0 时刻) 优先级都为 0。
每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减 到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。
如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果 优先级小于等于 3,则会被清除出优先缓存。
给定 T时刻以内的 M条订单信息,请你计算 T 时刻时有多少外卖店在优 先缓存中?
原题传送门
解题报告
和上面的日志那道题一样的思路,把每家店的订单分开,然后枚举时间,然后根据题目判断。
参考代码(C++版本)
#include <iostream>
using namespace std;
const int N = 2e5 + 10;
int cnt2[N];
pair<int, int>q[N];
int ans[N];
int cnt = 0;
int st[N];
int main() {
int n, m, t;
cin >> n >> m >> t;
for (int i = 1; i <= m; i++) cin >> q[i].first >> q[i].second;
for (int i = 1; i <= t; i++) {
for (int j = 1; j <= m; j++) {
if (i == q[j].first) {
cnt2[q[j].second] += 2;
st[q[j].second] = 1;
}
}
for (int i = 1; i <= n; i++) {
if (!st[i]) {
cnt2[i]--;
if (cnt2[i] < 0) cnt2[i] = 0;
}
else st[i] = 0;
if (cnt2[i] > 5) {
ans[i] = 1;
}
if (cnt2[i] <= 3 && ans[i] == 1) {
ans[i] = 0;
}
}
//cout<<i<<endl;
}
for (int i = 1; i <= n; i++) {
if (ans[i]) cnt++;
}
cout << cnt;
return 0;
}