牛客周赛 Round 92
A. 小红的签到题
点击查看代码
void solve() {
int n;
std::cin >> n;
std::string ans = std::string(1, 'a') + "_" + std::string(n - 2, 'a');
std::cout << ans << "\n";
}
B. 小红的模拟题
题意:从\((1, 1)\)到\((n, m)\)找一条路径。只能往下或者向右走。不能走陷阱。
爆搜即可。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<std::string> s(n);
for (int i = 0; i < n; ++ i) {
std::cin >> s[i];
}
std::vector<std::pair<int, int>> ans;
auto dfs = [&](auto & self, int x, int y) -> bool {
if (x == n - 1 && y == m - 1) {
ans.emplace_back(x, y);
return true;
}
if (x + 1 < n && s[x + 1][y] != '#' && self(self, x + 1, y)) {
ans.emplace_back(x, y);
return true;
}
if (y + 1 < m && s[x][y + 1] != '#' && self(self, x, y + 1)) {
ans.emplace_back(x, y);
return true;
}
return false;
};
dfs(dfs, 0, 0);
std::ranges::reverse(ans);
for (int i = 0; i + 1 < ans.size(); ++ i) {
if (ans[i + 1].first > ans[i].first) {
std::cout << "S";
} else {
std::cout << "D";
}
}
std::cout << "\n";
}
C. 小红的方神题
题意:对于数组\(a\),对其进行一次操作会变成一个长度为\(n-1\)的数组,第\(i\)个元素是\(|a_i - a_{i+1}|\)。要求构造一个长度为\(n\)的排列,使得经过\(n-1\)次操作后数组变成一个元素\(n-2\)。
构造\(1, n, n - 1, ... 2\)这样的数组,操作一次后变成\(n - 1, 1, 1, ..., 1\)。再操作变成\(n-2, 0, 0, 0, ..., 0\)。发现\(n-2\)一定留在最后且不会变化了。
点击查看代码
void solve() {
int n;
std::cin >> n;
if (n < 3) {
std::cout << -1 << "\n";
return;
}
std::vector<int> ans(n);
ans[0] = 1;
for (int i = 1; i < n; ++ i) {
ans[i] = n - i + 1;
}
for (int i = 0; i < n; ++ i) {
std::cout << ans[i] << " \n"[i == n - 1];
}
}
D. 小红的数学题
题意:给你\(k\),找\(p, q\)满足\(p + q = k\)且\(x^2 - px + q\)有两个正整数解。
设方程两个解为\(a, b\)。根据韦达定理:\(a + b = p, ab = q\),又因为\(p + q = k\),所以\(a + b + ab = k\),两边加一可得\((a + 1)(b + 1) = k + 1\)。
找一个\(k+1\)的因子求解即可。
点击查看代码
void solve() {
i64 k;
std::cin >> k;
++ k;
for (i64 i = 2; i * i <= k; ++ i) {
if (k % i == 0) {
i64 j = k / i;
i64 a = i - 1, b = j - 1;
std::cout << a + b << " " << a * b << "\n";
return;
}
}
std::cout << -1 << "\n";
}
E. 小红的ds题
题意:构造一棵二叉树,满足第\(i\)层有\(a_i\)个点。
模拟。记录上一层的点,每次一直把没用过的点给挂上去,直到满足有\(a_i\)个点。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
int m = std::accumulate(a.begin(), a.end(), 0);
std::vector<int> l(m + 1, -1), r(m + 1, -1);
std::vector<int> last{1};
for (int i = 1, j = 2; i < n; ++ i) {
std::vector<int> cur;
for (auto & u : last) {
cur.push_back(j);
l[u] = j ++ ;
-- a[i];
if (a[i] == 0) {
break;
}
cur.push_back(j);
r[u] = j ++ ;
-- a[i];
if (a[i] == 0) {
break;
}
}
last = cur;
}
std::cout << 1 << "\n";
for (int i = 1; i <= m; ++ i) {
std::cout << l[i] << " " << r[i] << "\n";
}
}
F. 小红的小苯题
题意:构造一个\(n \times m\)的数组,使得每行的异或和与每列的异或和组成一个\([1, n + m]\)的排列。
记第\(i\)行的异或和为\(R_i\),第\(j\)列异或和为\(C_i\)。那么有\(\sum_{i=1}^{n} R_i = \sum_{j=1}^{m} C_i\)。那么\(R_i \oplus C_i = 0\)。因为\(R_i \oplus C_i\)是\([1, n + m]\)的异或和,那么我们需要\(\oplus_{i=1}^{n+m} = 0\)。这是个经典问题,\(\oplus_{i=1}^{n} = 0\)那么\(n \equiv 3 \pmod{4}\)。那么\(n + m \not\equiv 3 \pmod{4}\)无解。
对于有解的情况,我们可以让\(R_i = i, C_j - n + j\)。可以这样构造:\(a[i][m] = i(i\in [1, n - 1]), a[m][j] = n + j, j \in [1, m - 1]\)。然后让第\(i\)行异或和为\(n\),那么可以求解出\(a[n][m]\)来。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
if ((n + m) % 4 != 3) {
std::cout << -1 << "\n";
return;
}
std::vector a(n, std::vector<int>(m));
for (int i = 0; i + 1 < n; ++ i) {
a[i][m - 1] = i + 1;
}
for (int j = 0; j + 1 < m; ++ j) {
a[n - 1][j] = n + j + 1;
a[n - 1][m - 1] ^= n + j + 1;
}
a[n - 1][m - 1] ^= n;
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
std::cout << a[i][j] << " \n"[j == m - 1];
}
}
}

浙公网安备 33010602011771号