前言:先说一下重现赛,重现赛因为打的时候时间比较紧,思维比较乱,就做出了前三道,D题二分了半天没写出来,E题我本来想用bfs特判一下去做,但是没做出来,F题压根没看(在此之前没有做过构造题)
D题太棒了
A.小红的签到题
水题,先计算出通过题目数 / 每个人的题目数,为本场人数不限制下最多的a题数, 如果人没有那么多的话,就直接输出人数喽。B
#include <bits/stdc++.h> using namespace std; int main() { int a, b, c; cin >> a >> b >> c; int res = c / a; if(res < b) cout << res; else cout << b; }
B.小红的ABC
说实话我这个题的做法很废,我直接用的n^3莽的,正解应该是最短字符串有且只有两种情况,2个的长度,3个的长度。
#include <bits/stdc++.h> using namespace std; bool adjust(string s) { string a = s; reverse(s.begin(), s.end()); return a == s; } int main() { string c; cin >> c; int ans = 100; for(int i = 0; i < c.size(); i ++ ) for(int j = i + 1; j < c.size();j ++ ) { string res; for(int k = i; k <= j; k ++ ) { res += c[k]; } if(adjust(res) && res.size() > 1) { int r = res.size(); ans = min(ans, r); } } if(ans != 100) cout << ans; else cout << -1; return 0; }
C. 小红的口罩
这个题刚拿到的时候下意识以为dp,看了一会发现就是个小根堆的问题,n * logn就可以过了
处理:开一个小根堆q,每天取不舒适度最低的口罩,然后让该口罩不舒适度乘以2后扔进堆内,如果超过k天了,就break一下,输出当前记录的天数
#include <bits/stdc++.h> using namespace std; priority_queue<int, vector<int>, greater<int>> q; int main() { int n, k; cin >> n >> k; for(int i =0; i < n; i ++ ) { int x; cin >> x; q.push(x); } int day = 0; while(1) { int t = q.top(); q.pop(); q.push(t * 2); if(t > k) break; else { k -= t; day ++; } } cout << day; return 0; }
D. 小红的数组
这个题我wa了三次,最后实在是二分不出答案,看的别人的题解;
引入(墙裂推荐,太妙了):upper_bound(a, a + n, x) 返回长度为n的数组的第一个大于x的数的地址
lower_bound(a, a + n, x) 返回长度为n的数组的第一个大于等于x的数的地址
处理:二分做法(双指针先不想了,有点废) 对于数组中的任意一个数a,找到a * b > k的b的最小值,即找到数组中大于1.0 * k / a (防止精度损失)的第一个数,那么这个数对于大于k的数的贡献就是n - l(upperbound返回的数组下标) + 1(如果找不到就直接返回最后一位的后一位,看代码就懂了!),对于一个等于k的数的贡献是l - r(lowerbound返回的数组下标)(妙啊!!),对于小于k的数贡献r - i - 1;
//双指针算法 #include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e6 + 10; int a[N], n, k; signed main() { cin >> n >> k; for(int i = 1; i <= n; i ++ ) cin >> a[i]; sort(a + 1, a + n + 1); int res1 = 0, res2 = 0, res3 = 0; int l, r; for(int i = 1; i <= n; i ++ ) { int r = lower_bound(a + i + 1, a + n + 1, 1.0 * k / a[i]) - a; int l = upper_bound(a + i + 1, a + n + 1, 1.0 * k / a[i]) - a; res1 += n - l + 1; //等于的情况 = l - r res2 += l - r; res3 += r - i - 1; } cout << res1 << " " << res2 << " " << res3; return 0; }
E: 小红的rpg游戏
这个题我本来是想用对bfs的几个点特殊处理来解决,毕竟是一个迷宫的题,但是wa了7次依然没有做对。
思路:注意到怪物的数量不超过10个,可以直接用二进制状态压缩来枚举走不走这个怪物的位置,开个sum,保证当前怪物对自己造成的伤害总量小于sum,然后bfs求一下最短路就可以(注意!求得是最短路径,不是最少消耗生命,我刚开始看错题了,直接原地起飞)
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 100;
char g[N][N];
int n, m, life, ans = 0x3f3f3f3f;
int step[N][N];
bool xx[N][N];
struct Node {
int x, y, h;
}monster[N];
void bfs()
{
memset(step, -1, sizeof step);
queue<PII> q;
q.push({0, 0});
step[0][0] = 0;
while(!q.empty()) {
int x = q.front().first, y = q.front().second;
q.pop();
int dir[][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for(int k = 0; k < 4; k ++ ) {
int dx = x + dir[k][0], dy = y + dir[k][1];
if(step[dx][dy] == -1 && dx >= 0 && dx < n && dy >= 0 && dy < m && xx[dx][dy])
step[dx][dy] = step[x][y] + 1, q.push({dx, dy});
}
}
if(step[n - 1][m - 1] != -1)
ans = min(ans, step[n - 1][m - 1]);
}
int main()
{
cin >> n >> m >> life;
for(int i = 0; i < n; i ++ ) cin >> g[i];
int cnt = 0;
for(int i = 0; i < n; i ++ )
for(int j = 0; j < m; j ++ ) {
if(g[i][j] >= '1' && g[i][j] <= '9')
monster[cnt ++] = {i, j, g[i][j] - '0'};
}
//for(int i = 0; i < cnt; i ++ ) cout << monster[i].x << " " << monster[i].y << endl;
for(int i = 0; i < (1 << cnt); i ++ ) {
int sum = 0;
for(int i = 0; i < n; i ++ )
for(int j = 0; j < m; j ++)
if(g[i][j] == '.') xx[i][j] = 1;
else xx[i][j] = 0;
for(int j = 0; j < 10; j ++ ) {
if((i >> j) & 1) {
int x = monster[j].x, y = monster[j].y, h = monster[j].h;
xx[x][y] = 1;
sum += h;
}
}
/*cout << sum << endl;
for(int i = 0; i < n; i ++ ) {
for(int j = 0; j < m; j ++ ) cout << xx[i][j] << " ";
puts("");
}
cout << endl;*/
if(sum >= life) continue;
bfs();
}
if(ans == 0x3f3f3f3f) cout << -1;
else cout << ans;
return 0;
}
F:小红的375
人生第一个构造题
注意到375 = 3 * 125,只需要判断这个数各位加起来是不是3的倍数和他的后三位是不是125的倍数即可。
处理:开一个桶记录一下各个数的出现次数
这个题妙在对前导0的处理,在当下adjust情况下是可行方案的时候,从大的tong(9)开始往小的tong倒就可以。
#include <bits/stdc++.h> using namespace std; int tong[10]; string adjust[8] ={"000", "500", "250", "750", "125", "375", "625", "875"}; int main() { string s; cin >> s; int sum = 0; for(int i : s) { tong[i - '0'] ++; sum += i - '0'; } if(sum % 3 != 0) { cout << -1; return 0; } for(int i = 0; i < 8; i ++ ) { bool flag = 0; for(int j = 0; j < 3; j ++ ) { tong[adjust[i][j] - '0'] --; if(tong[adjust[i][j] - '0'] < 0) flag = 1; } if(!flag) { for(int j = 9; j >= 0; j -- ) while(tong[j]) tong[j] --, cout << j; cout << adjust[i]; return 0; } for(int j = 0; j < 3; j ++ ) { tong[adjust[i][j] - '0'] ++; } } cout << -1; return 0; }