河南萌新联赛2024第(二)场:南阳理工学院
A - 国际旅行Ⅰ
因为保证联通,所以直接排序就好了
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using vi = vector<int>;
i32 main() {
int n, m, q;
cin >> n >> m >> q;
vi a(n);
for(int &i : a) cin >> i;
sort(a.begin(), a.end());
for(int x, y; m; m --)
cin >> x >> y;
for(int x; q; q--){
cin >> x, x--;
cout << a[x] << "\n";
}
return 0;
}
D - A*BBBB
直接用高精度是不可以的,但是我们可以用先成一个\(b\)然后再乘法\(11111\)就可以,这样的话就可以使用前缀和模拟高精度就好了。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using vi = vector<int>;
void solve() {
string a, b;
cin >> a >> b;
reverse(a.begin(), a.end());
int n = a.size(), m = b.size(), t = b[0] - '0';
a = " " + a;
vector<int> ans;
int sum = 0, now = 0, carry = 0;
for (int i = 1; i < n + m; i++) {
if (i <= n) sum += a[i] - '0';
if (i > m) sum -= a[i - m] - '0';
now = (sum * t + carry) % 10;
carry = (sum * t + carry) / 10;
ans.push_back(now);
}
if (carry > 0) cout << carry;
else {
while (ans.size() > 1 and ans.back() == 0)
ans.pop_back();
}
ranges::reverse(ans);
for (auto i: ans) cout << i;
cout << "\n";
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int TC;
for (cin >> TC; TC; TC--)
solve();
return 0;
}
E - “好”字符
把\(b\)串存两边,题目就变成在\(b\)串查询\(a\)串出现的次数。但是这里要剔除其他字母的影响,所以可以用*
表示一个通配符就好了。剩下用kmp就好了。
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using vi = vector<int>;
vi prefix_function(const string &s){
int n = s.size();
vi pi(n);
for(int i = 1, j; i < n; i ++) {
j = pi[i - 1];
while(j > 0 and s[i] != s[j]) j = pi[j - 1];
if(s[i] == s[j]) j ++;
pi[i] = j;
}
return pi;
}
bool kmp(const string &text, const string &pattern) {
string cur = pattern + "#" + text;
int n = text.size(), m = pattern.size();
vi lps = prefix_function(cur);
for(int i = m + 1; i <= n + m; i ++) {
if(lps[i] == m) return true;
}
return false;
}
i32 main() {
int n;
cin >> n;
string s, t;
cin >> s >> t, t = t + t;
vector<i.nt> cntS('z' + 1), cntT('z' + 1);
for(auto i : s)
cntS[i] = 1;
for(auto i : t)
cntT[i] = 1;
int res = 0;
for(char c = 'a'; c <= 'z'; c ++) {
if( cntS[c] == 0 or cntT[c] == 0) continue;
string ss = s, tt = t;
for(auto &i : ss)
if(i != c) i = '*';
for(auto &i : tt)
if(i != c) i = '*';
if(kmp(tt, ss)) res ++;
}
cout << res;
return 0;
}
F - 水灵灵的小学弟
两个人都是DHY
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using vi = vector<int>;
i32 main() {
int n;
cin >> n;
while(n --) cout << "DHY\n";
return 0;
}
G - 小w和大W的决斗。
在二维网格中如果要想将军队合并,就需要知道每个军队之间的距离,我们可以跑bfs来实现,当知道每个点之 间的距离之后我们跑一下最小生成树就可以知道最少多少天可以将军队合并了,如果军队与军队之间被阻挡无法到 达,则输出No。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = INT_MAX / 2;
const vi dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0};
class dsu {
private:
vector<int> fa;
public:
dsu(int n = 1) {
fa = vector<int>(n + 1, -1), fa[0] = 0;
}
int getfa(int x) {
if (fa[x] < 0) return x;
return fa[x] = getfa(fa[x]);
}
void merge(int x, int y) {
x = getfa(x), y = getfa(y);
if (x == y) return;
if (fa[x] > fa[y]) swap(x, y);
fa[x] += fa[y], fa[y] = x;
}
bool same(int x, int y) {
x = getfa(x), y = getfa(y);
return (x == y);
}
};
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<pii> pos;
vector<string> g(n);
for (auto &gi: g) cin >> gi;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (g[i][j] == '*')
pos.emplace_back(i, j), cerr << i << " , " << j << "\n";
auto bfs = [=](int sx, int sy) {
vector dis(n, vi(m, inf));
queue<pii> q;
q.emplace(sx, sy);
dis[sx][sy] = 0;
while (not q.empty()) {
auto [x, y] = q.front();
q.pop();
for (int i = 0, fx, fy; i < 4; i++) {
fx = x + dx[i], fy = y + dy[i];
if (fx < 0 or fy < 0 or fx >= n or fy >= m) continue;
if (g[fx][fy] == '#') continue;
if (dis[fx][fy] <= dis[x][y] + 1) continue;
dis[fx][fy] = dis[x][y] + 1;
q.emplace(fx, fy);
}
}
return dis;
};
vector<array<int, 3>> edge;
for (int i = 0; i < pos.size(); i++) {
auto [xi, yi] = pos[i];
auto dis = bfs(xi, yi);
for (int j = 0; j < i; j++) {
auto [xj, yj] = pos[j];
if (dis[xj][yj] == inf) {
cout << "No\n";
return 0;
}
edge.push_back({dis[xj][yj], i + 1, j + 1});
}
}
sort(edge.begin(), edge.end());
int res = 0;
int t = pos.size();
dsu d(t);
for (auto &[w, x, y]: edge) {
if (d.same(x, y)) continue;
res += w, d.merge(x, y);
}
cout << res;
return 0;
}
H - 狼狼的备忘录
小模拟,善用 STL 就好
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using vi = vector<int>;
i32 main() {
map<string, vector<string>> info;
int T;
for(cin >> T; T; T--) {
string name;
cin >> name;
int k;
for(cin >> k; k; k --){
string s;
cin >> s;
info[name].push_back(s);
}
}
for(auto &[name, it] : info){
sort(it.begin(), it.end());
it.resize(unique(it.begin(), it.end()) - it.begin());
for(auto &s : it)
reverse(s.begin(), s.end());
vector<string> newIt;
for(const auto &s: it){
bool flag = false;
for(const auto &t : it){
if(t.size() < s.size() or s == t) continue;
if(t.substr(0, s.size()) != s) continue;
flag = true;
break;
}
if(flag) continue;
newIt.push_back(s);
}
for(auto &s: newIt)
reverse(s.begin(), s.end());
sort(newIt.begin(), newIt.end());
it = move(newIt);
}
cout << info.size() << "\n";
for(auto &[name, it]: info){
cout << name << " " << it.size();
for(auto s : it) cout << " " << s;
cout << "\n";
}
return 0;
}
I - 重生之zbk要拿回属于他的一切
暴力匹配
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using vi = vector<int>;
i32 main() {
int n;
cin >> n;
string s;
cin >> s;
int cnt = 0;
for(int i = 0; i + 4 < n; i ++)
cnt += s.substr(i, 5) == "chuan";
cout << cnt;
return 0;
}
J - 这是签到
拉普拉斯展开
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using vi = vector<int>;
int calc(vector<vector<int>> a){
int n = a.size(), sum = 0;
if(n == 1) return a[0][0];
for(int i = 0; i < n; i ++){
vector<vi> b;
for(int j = 1; j < n; j ++ ){
b.push_back(vi());
for(int k = 0; k < n; k ++) {
if(k == i) continue;
b.back().push_back(a[j][k]);
}
}
sum += a[0][i] * pow(-1, i) * calc(b);
}
return sum;
}
i32 main() {
int n, m, N;
cin >> n >> m, N = max(n, m);
vector<vi> a(N, vi(N));
for(int i = 0; i < n; i ++)
for(int j = 0; j < m; j ++)
cin >> a[i][j];
int res = INT_MAX;
while(not a.empty()){
res = min(res, calc(a));
a.pop_back();
for(auto &ai : a)
ai.pop_back();
}
cout << res;
return 0;
}