西南民族大学 春季 2023 训练赛 7
L1-1 人与神
To iterate is human, to recurse divine.
L1-2 两小时学完C语言
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m, k;
cin >> n >> m >> k;
cout << max(0, n - m * k);
return 0;
}
L1-3 强迫症
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
if (s.size() == 6) {
cout << s.substr(0, 4) << "-" << s.substr(4, 2);
} else {
int t = (s[0] - '0') * 10 + s[1] - '0';
if (t < 22) cout << 20;
else cout << 19;
cout << s[0] << s[1] << "-" << s[2] << s[3];
}
return 0;
}
L1-4 降价提醒机器人
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
double m;
cin >> n >> m;
for (double x; n; n--) {
cin >> x;
if (m > x) printf("On Sale! %.1lf\n", x);
}
}
L1-5 大笨钟的心情
#include <bits/stdc++.h>
using namespace std;
int main(){
vector<int> a(24);
for( auto &i : a ) cin >> i;
for( int x ; true; ){
cin >> x;
if( x < 0 || x > 23 ) break;
cout << a[x];
if( a[x] > 50 ) cout << " Yes\n";
else cout << " No\n";
}
}
L1-6 吉老师的回归
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
if (n == m) {
cout << "Wo AK le\n";
return 0;
}
getchar();
for (int i = 1; i <= n; i++) {
string s;
getline(cin, s);
if (s.find("easy") == -1 && s.find("qiandao") == -1) {
if (m > 0) m--;
else {
cout << s << "\n";
return 0;
}
}
}
cout << "Wo AK le\n";
return 0;
}
L1-7 天梯赛的善良
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
int a = 0, b = 0, c = INT_MAX, d = INT_MIN;
cin >> n;
for (int x; n; n--) {
cin >> x;
if (x < c) c = x, a = 1;
else if (x == c) a++;
if (x > d) d = x, b = 1;
else if (x == d) b++;
}
cout << c << " " << a << "\n" << d << " " << b << "\n";
return 0;
}
L1-8 乘法口诀数列
#include <bits/stdc++.h>
using namespace std;
int main(){
int a , b , n ;
cin >> a >> b >> n;
vector<int> v(2);
v[0] = a , v[1] = b;
for( int i = 2 , x ; i < n ; i ++ ){
x = v[i-1] * v[i-2];
if( x > 9 ) v.push_back(x / 10) , v.push_back(x % 10);
else v.push_back(x);
}
for( int i = 0 ; i < n ; i ++ )
cout << v[i] << " \n"[i == n-1 ];
return 0;
}
L2-1 包装机
小模拟,用栈模拟一下筐就好了。注意对筐的操作前一定要先检查筐的状态。
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m, s;
cin >> n >> m >> s;
vector<int> pos(n + 1, 0);
vector<string> t(n + 1);
stack<char> box;
string ans;
for (int i = 1; i <= n; i++)
cin >> t[i];
for (int x;;) {
cin >> x;
if (x == -1) break;
else if (x == 0) {
if (!box.empty()) ans += box.top(), box.pop();
} else {
if (pos[x] == m) continue;
if (box.size() == s) ans += box.top(), box.pop();
box.push(t[x][pos[x]]), pos[x]++;
}
}
cout << ans << "\n";
return 0;
}
L2-2 病毒溯源
从所有的叶子简单,方向还原出序列后,统计最长且最小的即可
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int main() {
int n = read();
vector<int> cur, ans, fa(n, -1), d(n, 0);
for (int i = 0, k, x; i < n; i++) {
d[i] = k = read();
for (; k; k--)
x = read(), fa[x] = i;
}
for (int i = 0, t; i < n; i++) {
if (d[i]) continue;
cur.clear();
t = i;
while (t != -1) cur.push_back(t), t = fa[t];
reverse(cur.begin(), cur.end());
if (cur.size() > ans.size()) ans = cur;
else if (cur.size() == ans.size() && cur < ans) ans = cur;
}
cout << ans.size() << "\n";
for (auto i: ans)
cout << i << " \n"[i == ans.back()];
return 0;
}
L2-3 清点代码库
用 map统计没种出现的次数。然后对所有的种类进行排序
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int main() {
int n = read();
vector<int> cur, ans, fa(n, -1), d(n, 0);
for (int i = 0, k, x; i < n; i++) {
d[i] = k = read();
for (; k; k--)
x = read(), fa[x] = i;
}
for (int i = 0, t; i < n; i++) {
if (d[i]) continue;
cur.clear();
t = i;
while (t != -1) cur.push_back(t), t = fa[t];
reverse(cur.begin(), cur.end());
if (cur.size() > ans.size()) ans = cur;
else if (cur.size() == ans.size() && cur < ans) ans = cur;
}
cout << ans.size() << "\n";
for (auto i: ans)
cout << i << " \n"[i == ans.back()];
return 0;
}
L2-4 哲哲打游戏
建图然后模拟一下即可
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int main() {
int n = read(), m = read();
vector<vector<int>> e(n + 1);
for (int i = 1, k; i <= n; i++) {
k = read(), e[i] = vector<int>(k);
for (auto &j: e[i]) j = read();
}
vector<int> p(105);
int now = 1;
for (int op, x; m; m--) {
op = read(), x = read();
if (op == 0) now = e[now][x - 1];
else if (op == 1) cout << now << "\n", p[x] = now;
else now = p[x];
}
cout << now << "\n";
return 0;
}
L3-1 森森旅游
正向建图以现金为代价,反向建图以旅游金为代价。分别从起点和终点两边 dij 统计最小花费,然后枚举兑换旅游金的点统计出全局最优解。
对于修改汇率,用multiset
维护说有点兑换的代价,每次删掉就插入新的,begin()
就是每次修改后的答案。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
const int INF = 1e18;
int n, m, p;
typedef pair<int, int> pii;
int32_t main() {
n = read(), m = read(), p = read();
vector<int> a(n + 1);
vector<vector<pii>> e(n + 1), g(n + 1);
for (int u, v, c, d; m; m--) {
u = read(), v = read(), c = read(), d = read();
e[u].emplace_back(v, c);
g[v].emplace_back(u, d);
}
vector<int> d1(n + 1, INF), d2(n + 1, LLONG_MAX);
d1[1] = 0;
priority_queue<pii, vector<pii>, greater<pii> > q;
q.emplace(0, 1);
vector<bool> vis(n + 1, false);
while (!q.empty()) {
auto [d, u] = q.top();
q.pop();
if (vis[u]) continue;
vis[u] = true;
for (auto [v, w]: e[u]) {
if (vis[v] || d1[v] <= d + w) continue;
d1[v] = d + w, q.emplace(d1[v], v);
}
}
d2[n] = 0;
q.emplace(0, n);
vis = vector<bool>(n + 1, false);
while (!q.empty()) {
auto [d, u] = q.top();
q.pop();
if (vis[u]) continue;
vis[u] = true;
for (auto [v, w]: g[u]) {
if (vis[v] || d2[v] <= d + w) continue;
d2[v] = d + w, q.emplace(d2[v], v);
}
}
for (int i = 1; i <= n; i++) a[i] = read();
vector<int> b(n + 1, INF);
multiset<int> ans;
for (int i = 1; i <= n; i++) {
if (d1[i] != LLONG_MAX && d2[i] != LLONG_MAX)
b[i] = d1[i] + (d2[i] + a[i] - 1ll) / a[i];
ans.insert(b[i]);
}
for (int x, y; p; p--) {
x = read(), y = read();
if (d1[x] != LLONG_MAX && d2[x] != LLONG_MAX) {
ans.erase(ans.lower_bound(b[x]));
a[x] = y, b[x] = d1[x] + (d2[x] + y - 1ll) / y;
ans.insert(b[x]);
}
printf("%lld\n", *ans.begin());
}
return 0;
}
L3-2 还原文件
其实就是写一个暴搜,每次暴力匹配出可以放进去的碎片即可。
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int n , m;
vector<int> h;
vector<vector<int>> g;
vector<bool> vis;
vector<int> ans;
void dfs( int pos ){
if( pos == n-1 ){
for( auto i : ans )
cout << i << " \n"[i==ans.back()];
exit(0);
}
for( int i = 0 ; i < m ; i ++ ){
if( vis[i] ) continue;
bool flag = true;
for( int j = 0 , k = pos ; flag && j < g[i].size() ; j ++ , k ++ )
if( h[k] != g[i][j] ) flag = false;
if( flag == false ) continue;
vis[i] = true , ans.push_back(i+1);
dfs( pos + g[i].size() - 1 );
vis[i] = false , ans.pop_back();
}
}
int main(){
n = read();
h = vector<int>(n);
for( auto & i : h ) i = read();
m = read();
g = vector<vector<int>>(m);
vis = vector<bool>(m , false);
for( int i = 0 , x ; i < m ; i ++ ){
x = read() , g[i] = vector<int>(x);
for( int j = 0 ; j < x ; j ++ ) g[i][j] = read();
}
dfs( 0 );
return 0;
}