CCPC 2021 四川省赛
A. Chuanpai
题目大意
\(1 \leq x,y \leq 6\),问有多少组x+y=k
解题思路
暴力模拟即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int k, ans = 0;
std::cin >> k;
for (int x = 1; x <= 6; x++) {
for (int y = x; y <= 6; y++) {
ans += x + y == k;
}
}
std::cout << ans << "\n";
}
}
K. K-skip Permutation
题目大意
给定n和k,要求构造一个n排列p使得\(p_i+k=p_{i+1}\)的数量尽可能多
解题思路
对每一个位置都尽可能一直找+k即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
const int N = 2e6 + 10;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n, k;
std::cin >> n >> k;
std::vector<int> f(N), ans;
for (int i = 1; i <= n; i++) {
int x = i;
while (!f[x] && x <= n) {
f[x] = 1;
ans.emplace_back(x);
x += k;
}
}
for (int i = 0; i < n; i++) {
if (i != n - 1)
std::cout << ans[i] << " ";
else
std::cout << ans[i];
}
}
H. NihongowaMuzukashiiDesu
题目大意
给定单词和变形规则,给出原单词,求变形单词
解题思路
按照题意模拟即可
代码实现
for _ in range(int(input())):
s = input()
if s == "ikimasu":
print("itte")
elif s[-7:] == "shimasu":
print(s[:-7] + "shite")
elif s[-6:] == "gimasu":
print(s[:-6] + "ide")
elif s[-6:] == "kimasu":
print(s[:-6] + "ite")
elif s[-6:] in ["mimasu", "bimasu", "nimasu"]:
print(s[:-6] + "nde")
elif s[-7:] == "chimasu":
print(s[:-7] + "tte")
elif s[-6:] == "rimasu":
print(s[:-6] + "tte")
elif s[-5:] == "imasu":
print(s[:-5] + "tte")
B. Hotpot
题目大意
n个人吃火锅,如果里面有他喜欢的食物则吃光然后幸福值+1,否则加入他喜欢的食物,每个人喜欢的食物都是唯一的循环操作m次这样的操作,问最后每个人的幸福值是多少
解题思路
显然2n步之后会回到初始状态,对于循环部分直接模拟计算,不完整的循环单独计算即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n, k, m;
std::cin >> n >> k >> m;
std::vector<int> a(n), aa(n), bb(n), ans(n), f(k + 1);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
if (f[a[i]]) {
f[a[i]] = 0;
aa[i]++;
} else {
f[a[i]] = 1;
}
}
bb = aa;
for (int i = 0; i < n; i++) {
if (f[a[i]]) {
f[a[i]] = 0;
bb[i]++;
} else {
f[a[i]] = 1;
}
}
if (m / (2 * n)) {
for (int i = 0; i < n; i++) {
ans[i] += m / (2 * n) * bb[i];
}
m = m % (2 * n);
}
if (m / n) {
for (int i = 0; i < n; i++) {
if (f[a[i]]) {
f[a[i]] = 0;
ans[i]++;
} else {
f[a[i]] = 1;
}
}
m = m % n;
}
for (int i = 0; i < m; i++) {
if (f[a[i]]) {
f[a[i]] = 0;
ans[i]++;
} else {
f[a[i]] = 1;
}
}
for (int i = 0; i < n; i++) {
std::cout << ans[i] << " \n"[i == n - 1];
}
}
}
D. Rock Paper Scissors
题目大意
b和d进行石头剪刀布游戏,输-1平0赢+1,每次b先手,b要最小化分数,d要最大化分数,两人都是聪明的,问最后的得分是多少
解题思路
先手显然影响不了比赛,只要最大分数是多即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
i64 b1, b2, b3, d1, d2, d3, ans = 0;
std::cin >> b1 >> b2 >> b3 >> d1 >> d2 >> d3;
i64 x1 = std::min(b1, d2), x2 = std::min(b2, d3), x3 = std::min(b3, d1);
ans += x1 + x2 + x3;
b1 -= x1;
b2 -= x2;
b3 -= x3;
d1 -= x3;
d2 -= x1;
d3 -= x2;
x1 = std::min(b1, d1);
x2 = std::min(b2, d2);
x3 = std::min(b3, d3);
b1 -= x1;
b2 -= x2;
b3 -= x3;
d1 -= x3;
d2 -= x1;
d3 -= x2;
ans -= b1 + b2 + b3;
std::cout << ans << "\n";
}
}
M. True Story
题目大意
给你n个人的速度,告诉你所有飞机延迟的时刻和延迟的时间,再给定最初的到机场的距离和登机时间,问有多少人能登机
解题思路
只要找到延时最久的飞机需要的时间即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n, k, x, p0, ans = 0;
std::cin >> n >> k >> x >> p0;
std::vector<int> s(n), t(k), p(k);
for (int i = 0; i < n; i++) {
std::cin >> s[i];
}
for (int i = 0; i < k; i++) {
std::cin >> t[i];
}
for (int i = 0; i < k; i++) {
std::cin >> p[i];
}
double v = x / p0;
for (int i = 0; i < k; i++) {
v = std::min(v, (double)x / (double)(p[i] - t[i]));
}
for (int i = 0; i < n; i++) {
if (s[i] >= v) {
ans++;
}
}
std::cout << ans << "\n";
}
L. Spicy Restaurant
题目大意
给你一张无向图,每个节点表示一个餐厅,点权代表餐厅辛辣值,再告诉你q个游客所在的餐厅和他能接受的辛辣值,求第i名游客和他可以接受辛辣值的最近餐厅
解题思路
注意到辛辣值的范围很小,因此可以考虑从辛辣值入手进行bfs,最后对每个游客能接受的辛辣值都检查一遍即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n, m, q;
std::cin >> n >> m >> q;
std::vector<std::array<int, 2>> W(n + 1);
for (int i = 1; i <= n; i++) {
std::cin >> W[i][0];
W[i][1] = i;
}
sort(W.begin(), W.end());
std::vector<std::vector<int>> g(n + 1), vis(101, std::vector<int>(n + 1));
for (int i = 1; i <= m; i++) {
int u, v;
std::cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
std::queue<std::array<int, 3>> que;
for (int i = 1; i <= n; i++) {
auto [w, u] = W[i];
que.push({w, u, 0});
}
while (!que.empty()) {
auto [w, u, dist] = que.front();
que.pop();
if (vis[w][u]) {
continue;
}
if (dist) {
vis[w][u] = dist;
} else {
vis[w][u] = -1;
}
for (auto v : g[u]) {
if (!vis[w][v]) {
que.push({w, v, dist + 1});
}
}
}
while (q--) {
int p, a, ans = INT_MAX;
std::cin >> p >> a;
for (int i = 1; i <= a; i++) {
if (vis[i][p]) {
ans = std::min(ans, vis[i][p]);
}
}
if (ans == -1) {
std::cout << 0 << "\n";
} else if (ans == INT_MAX) {
std::cout << -1 << "\n";
} else {
std::cout << ans << "\n";
}
}
}
E. Don’t Really Like How The Story Ends
题目大意
给你一张无向图,问要补多少条边才能使得dfs的结果为1~n
解题思路
由于要1~n,因此只用建从小到大的边即可,之后对着这张图进行dfs,统计已经正确变量的数量cnt,如果u连边刚好是cnt+1说明可以直接继续搜索,如果大于cnt+1说明缺少了到cnt+1的边,这时候需要补一条边并回溯一次,看是否需要多次补边,最后在每个联通分量之间都进行一次连接即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n, m;
std::cin >> n >> m;
std::vector<std::vector<int>> g(n + 1);
std::set<std::array<int, 2>> st;
while (m--) {
int u, v;
std::cin >> u >> v;
if (u > v) {
std::swap(u, v);
}
if (u == v || st.count({u, v})) {
continue;
}
st.insert({u, v});
g[u].push_back(v);
}
int cnt = 1, ans = 0;
for (auto &v : g) {
sort(v.begin(), v.end());
}
std::vector<int> vis(n + 1);
auto dfs = [&](auto &&self, int u) -> void {
if (vis[u]) {
return;
}
vis[u] = 1;
if (u >= n) {
return;
}
for (int i = 0; i < g[u].size(); i++) {
auto v = g[u][i];
if (v == cnt + 1) {
cnt++;
self(self, v);
} else if (v > cnt + 1) {
cnt++;
ans++;
self(self, cnt);
i--;
}
}
return;
};
for (int i = 1; i <= n; i++) {
if (!vis[i]) {
dfs(dfs, i);
ans++;
cnt++;
}
}
std::cout << ans - 1 << "\n";
}
}