牛客小白月赛94

1|0A - 小苯的九宫格


#include <bits/stdc++.h> using namespace std; int main(){ vector<int> a(11); for(int i = 1; i <= 9; i ++) cin >> a[i]; string s; cin >> s; for(auto i : s) cout << a[i - '0']; return 0; }

2|0B - 小苯的好数组


如果原数组不是好数组,则原数组的任意子序列都一定不是好数组。所以如果原数组是好数组,原数组就是最长的子序列。

#include <bits/stdc++.h> using namespace std; using vi = vector<int>; int main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vi a(n); for(auto & i : a) cin >> i; if(is_sorted(a.begin(), a.end())) cout << 0; else cout << n; }

3|0C - 小苯的数字合并


最优解一定是把前缀合并成一个或者把后缀合并成一个。所以可以提前前缀和预处理一下,然后枚举前缀或后缀的长度。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; #define int long long using vi = vector<int>; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vi a(n); for(auto & i : a) cin >> i; vi preMax(n), preMin(n), pre(n); preMax[0] = preMin[0] = pre[0] = a[0]; for(int i = 1; i < n; i ++) { preMax[i] = max(preMax[i - 1], a[i]); preMin[i] = min(preMin[i - 1], a[i]); pre[i] = pre[i - 1] + a[i]; } vi sufMax(n), sufMin(n), suf(n); sufMax[n - 1] = sufMin[n - 1] = suf[n - 1] = a[n - 1]; for(int i = n - 2; i >= 0; i --) { sufMax[i] = max(sufMax[i + 1], a[i]); sufMin[i] = min(sufMin[i + 1], a[i]); suf[i] = suf[i + 1] + a[i]; } int res = sufMax[0] - sufMin[0]; for(int i = 1; i < n; i ++) res = max(res, max(preMax[i - 1], suf[i]) - min(preMin[i - 1], suf[i])); for(int i = n - 2; i >= 0; i --) res = max(res, max(sufMax[i + 1], pre[i]) - min(sufMin[i + 1], pre[i])); cout << res << "\n"; return 0; }

4|0D - 小苯的排列构造


首先,如果合法,则ai1一定是ai的约数。

然后可以得到一个结论:如果若干个数xj满足gcd(ai1,xj)=ai,则第i位填谁没有影响。所以可以贪心的选择最小值,我们可以用双端队列来维护当前剩下了哪些数。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using vi = vector<int>; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vi a(n), p(n); for(auto & i : a) cin >> i; deque<int> q; p[0] = a[0]; for(int i = 1; i <= n; i ++) if(i != p[0]) q.push_back(i); for(int i = 1; i < n; i ++) { if(a[i-1] % a[i] != 0) { cout << "-1\n"; return 0; } int fail = 0; while(gcd(a[i - 1], q.front()) != a[i]) { q.push_back(q.front()), q.pop_front(); fail ++; if(fail > q.size()) { cout << "-1\n"; return 0; } } p[i] = q.front(), q.pop_front(); } for(auto i : p) cout << i << " "; return 0; }

5|0E/F - 小苯的01背包


这题和 普通背包的最大区别就是,普通背包选的物品越多,总体积和总价值一定递增,但是本题是递减。

考虑到依旧是求解最大价值,我们可以枚举价值然后求解最小体积。

我们枚举了价值s,物品i能够被选择的条件是(s&ai)=s。对于所有可以被选择的物品,我们一定是全选最优。

这样的话,对于easy版本,我们可以暴力的枚举价值就好了。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using vi = vector<int>; const int N = (1 << 11) - 1; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int n, k; cin >> n >> k; vi v(n), w(n); for(int i = 0; i < n; i ++) cin >> v[i] >> w[i]; for(int i = N, tmp; i > 0; i --) { tmp = N; for(int j = 0; j < n; j ++) if((i & w[j]) == i) tmp &= v[j]; if(tmp <= k) { cout << i << "\n"; return 0; } } cout << "0\n"; return 0; }

对于hard 版本,我们无法再枚举价值,我么可以考虑试填法。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using vi = vector<int>; const int N = (1 << 11) - 1; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int n, k; cin >> n >> k; vi v(n), w(n); for(int i = 0; i < n; i ++) cin >> v[i] >> w[i]; int res = 0; for(int i = 30; i >= 0; i --){ int tryRes = res | (1 << i), tmp = 0x7fffffff; for(int j = 0; j < n; j ++) if((tryRes & w[j]) == tryRes) tmp &= v[j]; if(tmp <= k) res = tryRes; } cout << res << "\n"; return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/18218556.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示