河南萌新联赛2024第(二)场:南阳理工学院
国际旅行Ⅰ
思路:排序后直接输出
void solve() {
int n, m, q;
cin >> n >> m >> q;
vector<int> a(n + 1);
for (int i = 1; i <= n; ++i) cin >> a[i];
vector<vector<int> > ve(n + 1);
for (int i = 1; i <= m; ++i) {
int u, v;
cin >> u >> v;
ve[u].push_back(v), ve[v].push_back(u);
}
sort(a.begin() + 1, a.end());
while (q --) {
int k;
cin >> k;
cout << a[k] << '\n';
}
}
A*BBBB
思路:
b的每一位数相同,将b的每一位拆分,可以将a * b看作a * b[0] + a * b[1] * 10 + a * b[2] * 100 + ...
可以用高精度乘法O(n)计算a乘上b[0]
但是如果对于加法部分这样枚举加是O(n2)的,所以考虑优化
已知bn为b的位数
将bn个数用加法运算方法依次从上往下表示出来,从低位开始加法计算
可以发现每一位上的bn个数的和可以用前缀和维护,然后模拟加法过程即可
(手动画画加法运算过程就可以看出加的哪些数)
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int, int>
const int N = 1e5 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;
vector<int> mul(vector<int> A, int b) {
vector<int> C;
int t = 0;
for (int i = 0; i < A.size() || t; ++i) {
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
void solve() {
string a, b;
cin >> a >> b;
vector<int> aa, bb;
for (int i = a.size() - 1; i >= 0; --i) aa.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; --i) bb.push_back(b[i] - '0');
if (a == "0" || b == "0") {
cout << "0\n";
return ;
}
vector<int> cc = mul(aa, bb[0]);
int cn = cc.size();
vector<int> sum(cn + 1);
std::reverse(cc.begin(), cc.end());
for (int i = 1; i <= cn; ++i) {
sum[i] = sum[i - 1] + cc[i - 1];
}
auto get = [=] (int l, int r) {
return sum[r] - sum[l - 1];
};
int m = bb.size() + cc.size() - 1;
vector<int> ans;
int t = 0;
for (int i = m, l = cn + 1, r = cn; i >= 1; --i) {
r = min(r, i);
if (l > 1) l --;
int num = get(l, r);
t += num;
ans.push_back(t % 10);
t /= 10;
}
if (t > 0) ans.push_back(t);
std::reverse(ans.begin(), ans.end());
for (auto v:ans) cout << v;
cout << '\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
cin >> T;
while (T--) {
solve();
}
return 0;
}
“好”字符
思路:
字符串哈希或kmp
将b串后面再跟一个b串,这样操作后的串里长度为n的子串都为b的循环同构串
只有26个字符,分别考虑每个字符是否是好的
对于一个字符,将其余字符都设为一样,现在问题就变为操作后的b串中是否存在为a的子串
用字符串哈希或kmp都可以处理
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int, int>
const int N = 2e6 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;
int kmp(string text, string pattern) {
int n = text.size(), m = pattern.size();
if (m == 0) {
return 0;
}
vector<int> next(m);
for (int i = 1, j = 0; i < m; i++) {
while (j > 0 && pattern[i] != pattern[j]) {
j = next[j - 1];
}
if (pattern[i] == pattern[j]) {
j++;
}
next[i] = j;
}
for (int i = 0, j = 0; i < n; i++) {
while (j > 0 && text[i] != pattern[j]) {
j = next[j - 1];
}
if (text[i] == pattern[j]) {
j++;
}
if (j == m) {
return i - m + 1;
}
}
return -1;
}
void solve() {
int n;
cin >> n;
string a, b;
cin >> a >> b;
// swap(a, b);
b = b + b;
vector<string> bb(26);
vector<string> aa(26);
for (int i = 0; i < 26; ++i) {
char op = 'a' + i;
bb[i] = b;
int cnta = 0, cntb = 0;
for (int j = 0; j < bb[i].size(); ++j) {
if (bb[i][j] == op) {
cntb ++;
continue;
}
bb[i][j] = '.';
}
aa[i] = a;
for (int j = 0; j < aa[i].size(); ++j) {
if (aa[i][j] == op) {
cnta ++;
continue;
}
aa[i][j] = '.';
}
if (cnta * 2 != cntb || cnta == 0) {
aa[i].clear();
}
}
int ans = 0;
for (int t = 0; t < 26; ++t) {
if (aa[t].empty()) continue;
if (kmp(bb[t], aa[t]) != -1) ans ++;
}
cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) {
solve();
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define int long long
#define PII pair<int, int>
//const int N = 2e6 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;
const int N = 2e6 + 5; // 最大字符串的个数
const int M = 2e6 + 10; // 题目中字符串的最大长度
const ull base = 131; // 131,13331不容易哈希碰撞
// p[i]:表示p的i次方
// h[i]:表示s[1~i]的哈希值,如h[2]表示字符串s前两个字符组成字符串的哈希值
ull p[N], h[N];
//int n;
// 预处理hash函数的前缀和,时间复杂度O(n)
void init(string s) {
// 下标从1开始
int n = s.size() - 1;
// p^0=1,空串哈希值为0
p[0] = 1, h[0] = 0;
for (int i = 1; i <= n; i++) {
p[i] = p[i - 1] * base;
h[i] = h[i - 1] * base + s[i]; // 前缀和计算公式
}
}
// 计算s[l~r](子串)的hash值,时间复杂度O(1)
ull get(int l, int r) {
return h[r] - h[l - 1] * p[r - l + 1]; // 区间和计算字串的hash值
}
// 判断s中的两个子串是否相同
bool substr(int l1, int r1, int l2, int r2) {
return get(l1, r1) == get(l2, r2);
}
// 求ss的哈希值(下标从0开始)
ull gethash(string ss) {
ull ret = 0;
for (int i = 0; i < ss.size(); ++i)
ret = ret * base + (ull) ss[i];
return ret;
}
void solve() {
int n;
cin >> n;
string a, b;
cin >> a >> b;
b = b + b;
vector<string> bb(26);
vector<string> aa(26);
for (int i = 0; i < 26; ++i) {
char op = 'a' + i;
bb[i] = ' ' + b;
int cnta = 0, cntb = 0;
for (int j = 0; j < bb[i].size(); ++j) {
if (bb[i][j] == op) {
cntb++;
continue;
}
bb[i][j] = '.';
}
aa[i] = a;
for (int j = 0; j < aa[i].size(); ++j) {
if (aa[i][j] == op) {
cnta++;
continue;
}
aa[i][j] = '.';
}
if (cnta * 2 != cntb || cnta == 0) {
aa[i].clear();
}
}
int ans = 0;
for (int t = 0; t < 26; ++t) {
if (aa[t].empty()) continue;
init(bb[t]);
int hasha = gethash(aa[t]);
for (int i = 1; i <= n; ++i) {
int hashb = get(i, i + n - 1);
if (hasha == hashb) {
ans ++;
break;
}
}
}
cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) {
solve();
}
return 0;
}
水灵灵的小学弟
void solve() {
int a, b;
cin >> a >> b;
cout << "DHY\n";
}
lxy的通风报信
思路:
首先军队数量最多为50,那么可以求出两两军队之间到达的最短距离,复杂度为50 * n * m
然后求最小生成树即可
#include <bits/stdc++.h>
using namespace std;
//#define int long long
#define PII pair<int, int>
const int N = 1e6 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
struct E {
int u, v, w;
bool operator<(const E &e) const {
return w < e.w;
}
};
int fa[100];
int find(int x) {
if (x != fa[x]) fa[x] = find(fa[x]);
return fa[x];
}
void solve() {
int n, m;
cin >> n >> m;
int cnt = 0;
map<int, int> id;
vector<string> s(n);
for (int i = 0; i < n; ++i) {
cin >> s[i];
for (int j = 0; j < m; ++j) {
if (s[i][j] == '*') {
id[i * m + j] = ++cnt;
}
}
}
vector<vector<int> > dis(cnt + 1, vector<int> (cnt + 1, INT32_MAX));
vector<int> st(n * m + 10);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (s[i][j] == '*') {
int stid = i * m + j;
queue<PII> q;
q.push({stid, 0});
st[stid] = stid;
while (q.size()) {
auto [uid, d] = q.front();
q.pop();
int x = uid / m, y = uid % m;
if (s[x][y] == '*') dis[id[stid]][id[uid]] = min(dis[id[stid]][id[uid]], d), dis[id[uid]][id[stid]] = min(dis[id[uid]][id[stid]], d);
for (int k = 0; k < 4; ++k) {
int xx = x + dx[k], yy = y + dy[k], vid = xx * m + yy;
if (xx < 0 || xx >= n || yy < 0 || yy >= m || st[vid] == stid || s[xx][yy] == '#') continue;
q.push({vid, d + 1});
st[vid] = stid;
}
}
}
}
}
vector<E> edge;
for (int i = 1; i <= cnt; ++i) {
for (int j = i + 1; j <= cnt; ++j) {
if (dis[i][j] == INT32_MAX) {
cout << "No";
return ;
}
edge.push_back({i, j, dis[i][j]});
}
}
sort(edge.begin(), edge.end());
for (int i = 1; i <= cnt; ++i) fa[i] = i;
int sum = 0;
for (int i = 0; i < edge.size(); ++i) {
int u = find(edge[i].u), v = find(edge[i].v);
if (u == v) continue;
fa[v] = u;
sum += edge[i].w;
cnt --;
if (cnt <= 1) break;
}
if (cnt <= 1) {
cout << sum;
} else cout << "No\n";
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) {
solve();
}
return 0;
}
狼狼的备忘录
思路:
数据不大,狠狠暴力
只要有一个串为另一个串的后缀就不要
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int, int>
const int N = 1e5 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;
void solve() {
int n;
cin >> n;
map<string, set<string>> f;
map<string, set<string> > g;
auto check = [&] (string na, string u) {
for (auto v:g[na]) {
if (u.size() > v.size()) {
bool ok = true;
for (int j = u.size() - 1, i = v.size() - 1; i >= 0; --j, --i) {
if (u[j] != v[i]) {
ok = false;
break;
}
}
if (ok) {
g[na].erase(v);
return true;
}
} else if (u.size() < v.size()) {
bool ok = true;
for (int j = u.size() - 1, i = v.size() - 1; j >= 0; --j, --i) {
if (u[j] != v[i]) {
ok = false;
break;
}
}
if (ok) return false;
}
}
return true;
};
for (int i = 0; i < n; ++i) {
string na;
cin >> na;
int k;
cin >> k;
for (int j = 0; j < k; ++j) {
string x;
cin >> x;
f[na].insert(x);
}
}
for (auto [na, ve]:f) {
for (auto v:ve) {
if (check (na, v)) g[na].insert(v);
}
}
cout << g.size() << '\n';
for (auto [na, ve]:g) {
cout << na << ' ';
cout << ve.size() << ' ';
for (auto v:ve) cout << v << ' ';
cout << '\n';
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) {
solve();
}
return 0;
}
重生之zbk要拿回属于他的一切
void solve() {
int n;
cin >> n;
string s;
cin >> s;
string a = "chuan";
int ans = 0;
for (int i = 0; i + 4 < s.size(); ++i) {
for (int j = 0, ii = i; j < a.size(); ++j, ++ii) {
if (a[j] != s[ii]) break;
if (j == a.size() - 1) ans ++, i += 4;
}
}
cout << ans;
}
这是签到
思路:
按照给的公式,枚举算所有排列
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int, int>
const int N = 1e5 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;
void solve() {
int n, m;
cin >> n >> m;
int ma = max(n, m);
vector<vector<int> > ve(ma + 1, vector<int> (ma + 1, 0));
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) cin >> ve[i][j];
int ans = LLONG_MAX;
// ans = ve[1][1];
// if (ma >= 2) ans = min(ans, ve[1][1] * ve[2][2] - ve[1][2] * ve[2][1]);
//// cout << ve[1][1] * ve[2][2] - ve[1][2] * ve[2][1] << '\n';
// if (ma >= 3) ans = min(ans, ve[1][1] * ve[2][2] * ve[3][3] + ve[1][2] * ve[2][3] * ve[3][1] + ve[1][3] * ve[2][1] * ve[3][2] -
// ve[1][3] * ve[2][2] * ve[3][1] - ve[1][1] * ve[2][3] * ve[3][2] - ve[1][2] * ve[2][1] * ve[3][3]);
for (int t = 1; t <= ma; ++t) {
vector<int> a(t);
int res = 0;
for (int i = 0; i < t; ++i) a[i] = i + 1;
do {
int cnt = 0;
for (int i = 0; i < t; ++i) {
for (int j = i + 1; j < t; ++j) {
cnt += (a[i] > a[j]);
}
}
int sum = 1;
for (int i = 0, j = 1; i < t; ++i, ++j) {
sum *= ve[j][a[i]];
}
if (cnt % 2) sum = -sum;
res += sum;
}while (next_permutation(a.begin(), a.end()));
// cout << res << '\n';
ans = min(ans, res);
}
cout << ans;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) {
solve();
}
return 0;
}