2024牛客暑期多校训练营8 题解
A - Haitang and Game
Question
给定一个集合
-
找出一对
,使得 和 。 -
将
插入 。
无法下棋的棋手输掉对局。当两位棋手都以最佳方式下棋时,您需要输出赢家。
Solution
其实这里是一个假博弈,
由于
设
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve() {
int N; cin >> N;
vector<int> A(N);
for (int i = 0; i < N; i++) cin >> A[i];
int M = *max_element(A.begin(), A.end());
vector<int> cnt(M + 1, 0);
for (auto &a : A) cnt[a] = 1;
int num = 0;
for (int i = M; i >= 1; i--) {
int g = 0;
for (int j = i; j <= M; j += i) {
if (cnt[j]) g = __gcd(g, j);
}
if (g == i) {
if (cnt[i] == 0) {
num += 1;
cnt[i] = 1;
}
}
}
if (num & 1)
cout << "dXqwq" << '\n';
else
cout << "Haitang" << '\n';
}
int main() {
ios::sync_with_stdio(false);
int T; cin >> T;
while (T--) solve();
return 0;
}
E - Haitang and Math
Question
海棠将正整数
例如,
给定一个正整数
Solution
考到了一个我以前不会的东西,然后就去学了一下
考虑到
我们需要找到
容易想到把
思考如何质因数分解,朴素来说,质因数分解就是
for (p : prime)
int cnt = 0
while (x % p == 0)
x /= p, cnt += 1
这样的时间复杂度是
我们这里的
考虑区间内
那么,如何才能找到第一个
这样就能把
关于这个的时间复杂度,我不知道怎么计算,题解给出是
Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn = 1e6 + 5;
constexpr int M = 108;
vector<int> prime;
int s(int x) {
int ret = 0;
while (x) {
ret += x % 10;
x /= 10;
}
return ret;
}
vector<int> get_prime() {
vector<int> prime;
vector<int> vis(maxn, 0);
for (int i = 2; i < maxn; i++) {
if (vis[i] == 0) {
prime.push_back(i);
for (int j = i + i; j < maxn; j += i)
vis[j] = 1;
}
}
return prime;
}
void solve() {
int n; cin >> n;
const int L = max(n - M, 1ll), R = n, len = R - L + 1;
vector<int> a(len);
vector<vector<pair<int, int>>> p(len, vector<pair<int, int>>(0));
for (int i = L; i <= R; i++) a[i - L] = i;
for (auto v : prime) {
int pos = (L + v - 1) / v * v - L;
if (pos >= len) continue;
for (int i = pos; i < len; i += v) {
int cnt = 0;
while (a[i] % v == 0) {
a[i] /= v; cnt += 1;
}
if (cnt) p[i].push_back({v, cnt});
}
}
for (int i = 0; i < len; i++) {
if (a[i] > 1) p[i].push_back({a[i], 1});
}
set<int> ans;
auto dfs = [&] (auto &&dfs, int pos, int now, vector<pair<int, int>> &p) -> void {
auto [pr, cnt] = p[pos];
if (pos == (int)p.size()) {
int Sm = s(now);
if (n % now == Sm) ans.insert(now);
return;
}
for (int i = 0; i <= cnt; i++) {
dfs(dfs, pos + 1, now, p);
now *= pr;
}
};
for (int i = 0; i < len; i++) {
if (p[i].empty()) continue;
dfs(dfs, 0, 1, p[i]);
}
cout << ans.size() << '\n';
}
signed main() {
ios::sync_with_stdio(false);
int T; cin >> T;
prime = get_prime();
while (T--) solve();
return 0;
}
J - Haitang and Triangle
Question
给定两个整数
- 恰好有
个长度为 的子区间,使得这些子区间中的数字构成一个(非退化的)三角形。
Solution
雨巨说:构造题就要多手玩,然后找到一些规律和性质,其实没有想象的那么难
我们先考虑极端情况,显然
我们能构造出一种
然后考虑
通过观察可以发现,
然后思考
用
Code
#include <bits/stdc++.h>
using namespace std;
void solve() {
int n, m; cin >> n >> m;
if (m == n - 2) {cout << -1 << '\n'; return;}
int p = n - m;
vector<int> res(n + 1, 0);
int l = 1, r = p;
for (int i = p - 0; i >= 1; i -= 3) res[i] = r--;
for (int i = p - 1; i >= 1; i -= 3) res[i] = r--;
for (int i = p - 2; i >= 1; i -= 3) res[i] = l++;
for (int i = p + 1; i <= n; i++) res[i] = i;
for (int i = 1; i <= n; i++) cout << res[i] << " \n"[i == n];
return ;
}
int main() {
ios::sync_with_stdio(false);
int T; cin >> T;
while (T--) solve();
return 0;
}
K - Haitang and Ava
Question
Ava 会在直播开始时说一段开场白。
有效开场白的条件如下:
-
空字符串是有效的开场白。
-
如果
是有效的开场白,那么 和 也是有效的开场白。 -
如果
是有效的开场白,那么 和 也是有效的开场白。 -
任何不能用上述方法构造的字符串都不是有效的开场白。
给定一个字符串
Solution
如果有
Code
#include <bits/stdc++.h>
using namespace std;
bool solve() {
string s; cin >> s;
while (!s.empty()) {
if (s.size() >= 5 && s.substr(0, 5) == "avava") s = s.substr(5);
else if (s.size() >= 3 && s.substr(0, 3) == "ava") s = s.substr(3);
else break;
}
return s.empty();
}
int main() {
ios::sync_with_stdio(false);
int T; cin >> T;
while (T--) cout << (solve() ? "Yes" : "No") << '\n
return 0;
}