The 2021 Sichuan Provincial Collegiate Programming Contest
The 2021 Sichuan Provincial Collegiate Programming Contest
A. Chuanpai
题意:给出总值k,将k分成x+y=k,x和y均小于7,最多分成多少组。
思路:暴力跑一遍,注意判重和xy的范围即可。
AC code:
void solve() {
int k; cin >> k;
int cnt = 0;
for (int i = 1; i <= k / 2; i ++) {
if (i < 7 && k - i < 7) {
cnt ++;
}
} cout << cnt << endl;
}
B. Hotpot
题意:
有0到n-1名游客围成一圈吃火锅,火锅配料有k种,第i名游客喜欢第 a i a_i ai种配料,最初每个游客幸福值为0,锅为空;
游客顺序下m步旗,由0->n-1…0->n-1的顺序循环进行操作,当轮到某个游客时:
- 锅中有食材 a i a_i ai,全吃掉获得1幸福值
- 否则幸福值不变,然后下入喜欢的食材
计算m步之后每位游客的幸福值
思路:
首先喜欢同一种食材的所有游客的幸福值操作是独立的,需要单独进行操作:
- 当喜欢同一种食材的人为奇数时,每2*n次操作为一轮,一轮后该食材的每个人幸福值+1;
- 为偶数时,n次操作为一轮,每轮中只有喜欢该食材的偶数位的幸福值+1;
- 统计m轮次中可以进行完整的几轮操作,然后对于余数进行单独操作幸福值;
AC code:
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
#define db double
#define pb push_back
#define fast() ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;
typedef pair<char, int> PCI;
typedef pair<int, int> PII;
const int N = 2e5+10, M = 2001;
const int INF = 0x3f3f3f3f3f, MOD = 998244353;
int T;
int cnt[N], a[N];
vector<int> g[N];
void solve() {
int n, k, m; cin >> n >> k >> m;
for (int i = 1; i <= k; i ++) g[i].clear();
for (int i = 0; i < n; i ++) {
cin >> a[i];
cnt[i] = 0;
g[a[i]].push_back(i);
}
for (int i = 1; i <= k; i ++) {
int now = g[i].size();
if (now == 0) continue;
if (now & 1) {
int u = m / (2 * n), v = m % (2 * n);
for (auto x : g[i]) cnt[x] += u;
int pos = 0;
if (v >= n) {
for (auto x : g[i]) {
if (pos) cnt[x] += 1;
pos ^= 1;
}
}
v %= n;
for (auto x : g[i]) {
if (x >= v) break;
if (pos) cnt[x] += 1;
pos ^= 1;
}
} else {
int u = m / n, v = m % n;
int pos = 0;
for (auto x : g[i]) {
if (pos) cnt[x] += u;
pos ^= 1;
}
pos = 0;
for (auto x : g[i]) {
if (x >= v) break;
if (pos) cnt[x] += 1;
pos ^= 1;
}
}
}
cout << cnt[0];
for (int i = 1; i < n; i ++) cout << ' ' << cnt[i];
cout << endl;
}
signed main() {
fast();
T = 1;
cin >> T;
while (T --) {
solve();
}
return 0;
}
D. Rock Paper Scissors
题意:明牌石头剪刀布,B先出牌,D后出牌,B胜总分-1, D胜总分+1,双方均以最优操作,最后得分为多少。
思路:由于B先手,D总能找出最优操作,能胜则胜,否则打平,最后无牌下才会让B胜,模拟这个过程即可。
AC code:
void solve() {
int br, bp, bs, dr, dp, ds; cin >> br >> bp >> bs >> dr >> dp >> ds;
int cnt = 0;
if (br) {
if (dp >= br) dp -= br, cnt += br, br = 0;
else br -= dp, cnt += dp, dp = 0;
if (dr >= br) dr -= br, br = 0;
else br -= dr, dr = 0;
if (ds >= br) ds -= br, cnt -= br, br = 0;
else br -= ds, cnt -= ds, ds = 0;
}
if (bp) {
if (ds >= bp) ds -= bp, cnt += bp, bp = 0;
else bp -= ds, cnt += ds, ds = 0;
if (dp >= bp) dp -= bp, bp = 0;
else bp -= dp, dp = 0;
if (dr >= bp) dr -= bp, cnt -= bp, bp = 0;
else bp -= dr, cnt -= dr, dr = 0;
}
if (bs) {
if (dr >= bs) dr -= bs, cnt += bs, bs = 0;
else bs -= dr, cnt += dr, dr = 0;
if (ds >= bs) ds -= bs, bs = 0;
else bs -= ds, ds = 0;
if (dp >= bs) dp -= bs, cnt -= bs, bs = 0;
else bs -= dp, cnt -= dp, dp = 0;
}
cout << cnt << endl;
}
H. Nihongo wa Muzukashii Desu
题意:略。
思路:按照样例模拟更换字符串即可,注意读题,“ikimasu"要变成"itte”;
AC code:
void solve() {
int n; cin >> n;
map<string, string> mp;
mp["chimasu"] = "tte";
mp["rimasu"] = "tte";
mp["mimasu"] = "nde";
mp["bimasu"] = "nde";
mp["nimasu"] = "nde";
mp["kimasu"] = "ite";
mp["gimasu"] = "ide";
mp["shimasu"] = "shite";
while (n --) {
string s; cin >> s;
if (s == "ikimasu") {
cout <<"itte" << endl;
continue;
}
for (auto [x, y] : mp) {
if (s.find(x) != s.npos) {
int t = s.find(x);
s.replace(t, x.size(), y);
cout << s << endl;
break;
}
}
}
}
K. K-skip Permutation
题意:略。
思路:循环标记判断即可,注意输出格式。
AC code:
void solve() {
int n, k; cin >> n >> k;
vector<int> st(n + 1, 0), ans;
for (int i = 1; i <= n; i ++) {
if (!st[i]) {
for (int j = i; j <= n; j += k) {
if (!st[j]) ans.pb(j), st[j] = 1;
else break;
}
}
}
cout << ans[0];
for (int i = 1; i < ans.size(); i ++) cout << ' ' << ans[i];
cout << endl;
}
L. Spicy Restaurant
题意:
在无向图n个火锅店的无向图中,第i个餐厅的辣度为 w i w_i wi,现在给出无向图的m条边,有q名游客想去吃火锅,现在给出每个人当前的位置和他们能承受的最大辣度,计算每个游客和能接受的辣度餐厅之间的最短距离。
思路:
辣度的范围很小,对同一种辣度的所有点进行BFS寻找靠近该辣度最近的其他店,用一个二维数组来记录某个辣度到某个点的最短距离。
AC code:
#include<bits/stdc++.h>
#define endl '\n'
#define db double
#define pb push_back
#define fast() ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;
typedef pair<char, int> PCI;
typedef pair<int, int> PII;
const int N = 1e5+10, M = 2001;
const int INF = 0x3f3f3f3f3f, MOD = 998244353;
int T;
int n, m, q;
int w[N];
vector<vector<int>> dis(101, vector<int> (N, INF));
vector<int> g[N];
map<int, vector<int>> mp;
void solve() {
cin >> n >> m >> q;
for (int i = 1; i <= n; i ++) {
cin >> w[i];
mp[w[i]].push_back(i);
dis[w[i]][i] = 0;
}
while (m --) {
int u, v; cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
for (int i = 1; i <= 100; i ++) {
queue<int> q;
for (auto x : mp[i]) q.push(x);
vector<int> st(n + 1, 0);
while (!q.empty()) {
auto t = q.front();
st[t] = 1;
q.pop();
for (auto nex : g[t]) {
dis[i][nex] = min(dis[i][t] + 1, dis[i][nex]);
if (!st[nex]) q.push(nex);
}
}
}
while (q --) {
int p, a; cin >> p >> a;
int ans = INF;
for (int i = 1; i <= a; i ++) {
ans = min(ans, dis[i][p]);
}
cout << (ans != INF ? ans : -1) << endl;
}
}
int main() {
fast();
T = 1;
//cin >> T;
while (T --) {
solve();
}
return 0;
}
M. True Story
题意:略;
思路:距离和每个人的速度是一定的,找到间隔时间最大的时间段看是否能到达即可;
AC code:
void solve() {
int n, k, x, po; cin >> n >> k >> x >> po;
for (int i = 1; i <= n; i ++) cin >> s[i];
for (int i = 1; i <= k; i ++) cin >> t[i];
for (int i = 1; i <= k; i ++) cin >> p[i];
vector<int> late;
late.push_back(po);
for (int i = 1; i <= k; i ++) late.push_back(p[i] - t[i]);
sort(late.begin(), late.end(), greater<int>());
int ans = 0, mx = late[0];
for (int i = 1; i <= n; i ++) {
if (mx * s[i] >= x) ans ++;
}
cout << ans << endl;
}