The 10th Jimei University Programming Contest

外校打星队伍,排名22/450,还算凑合吧。

1|0A. A+B问题


直接枚举进制

#include <bits/stdc++.h> using namespace std; using vi = vector<int>; void solve() { string str; vi a, b, s; cin >> str; for (auto c: str) { if (c >= '0' and c <= '9') a.push_back(c - '0'); else a.push_back(c - 'A' + 10); } cin >> str; for (auto c: str) { if (c >= '0' and c <= '9') b.push_back(c - '0'); else b.push_back(c - 'A' + 10); } cin >> str; for (auto c: str) { if (c >= '0' and c <= '9') s.push_back(c - '0'); else s.push_back(c - 'A' + 10); } auto f = [](vi a, int x) { if (*max_element(a.begin(), a.end()) >= x) return -1; int ans = 0; for (auto i: a) ans = ans * x + i; return ans; }; for (int i = 2, A, B, S; i <= 16; i++) { A = f(a, i); if (A == -1) continue; B = f(b, i); if (B == -1) continue; S = f(s, i); if (S == -1) continue; if (S == A + B) { cout << i << "\n"; return; } } } int main() { int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

2|0B. 看比赛


首先正反两遍最短路,这样就可以确定那些边一定是最短路上的边,删掉多余的方向和边就会形成一个有向无环图。

我们发现,在有向图上能一步到达 n 的点,对于这些点是先手必胜点。然后只能够走到先手必胜的点的点就是先手必败点,根据这个规律,我们把整张图反向,然后按照拓扑序根据这个规则去给点染色,最后判断 1 的属性即可。

#include <bits/stdc++.h> using namespace std; #define int long long using vi = vector<int>; using pii = pair<int, int>; const int inf = 1e18; void solve() { int n, m; cin >> n >> m; vector<vector<pair<int, int>>> e(n + 1); vector<vi> g(n + 1); vector<array<int, 3>> edge(m); for (auto &[u, v, w]: edge) { cin >> u >> v >> w; e[u].emplace_back(v, w); e[v].emplace_back(u, w); } auto dij = [n, e](int x) { vi dis(n + 1, inf); vi vis(n + 1, 0); dis[x] = 0ll; priority_queue<pii, vector<pii>, greater<pii>> q; q.emplace(0, x); while (!q.empty()) { auto [d, u] = q.top(); q.pop(); if (vis[u]) continue; vis[u] = 1; for (auto [v, w]: e[u]) { if (dis[v] <= d + w)continue; dis[v] = d + w; q.emplace(dis[v], v); } } return dis; }; auto d1 = dij(1) , d2 = dij(n); vi cnt(n+1) , f(n+1); for( auto [ u , v , w ] : edge ){ if( d1[u] + w + d2[v] == d1[n] ) g[v].push_back(u) , cnt[u] ++; else if ( d1[v] + w + d2[u] == d1[n] ) g[u].push_back(v) , cnt[v] ++; } queue<int> q; q.push(n); while( !q.empty() ){ int u = q.front(); q.pop(); for( auto v : g[u] ){ if( f[u] == 0 ) f[v] = 1; cnt[v] --; if( cnt[v] == 0 ) q.push(v); } } if( f[1] ) cout << "Little M is the winner.\n"; else cout << "Little I is the winner.\n"; return ; } int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

3|0C. 方格染色


#include <bits/stdc++.h> using namespace std; #define int long long using vi = vector<int>; using pii = pair<int, int>; const int inf = 1e18; int32_t main() { int n = 10, m = 10; vector f(n + 1, vector(m + 1, vi(3, 0))); f[0][0][0] = 1; for (int i = 1; i <= n; i++) { for (int j = 0; j <= i; j++) { for (int k = 0; k < 3; k++) { if (j == 0 and k > 0) continue; for (int l = 0; l < 3; l++) { if ((l & k) != 0) continue; if( j - (k > 0) == 0 and l != 0 ) continue; f[i][j][k] += f[i - 1][j - (k > 0)][l]; } } } } for (int i = 1; i <= n; i++) { for (int j = 0; j <= m; j++) { cout << accumulate(f[i][j].begin(), f[i][j].end(), 0ll) << " "; } cout << "\n"; } return 0; }

首先我写了一个这样的 dp 去打表,然后对于(n,k)的答案,发现当n<k时一定无解。

为了方便令n=nk+1,发现递推式子f(n,k)=2×k×f(n1,k)n1+f(n2,k),f(0,k)=0,f(1,k)=2

这样子我们自然可以得到一个O(nk)的递推,但是我发现k5×105,那么k的种类数最多就是1,2,3,这样取,也就是k(k1)25×105k最多大约是103中,这样的话配合记忆化就可以实现复杂度控制在O(108)这样

#include <bits/stdc++.h> using namespace std; #define int long long using vi = vector<int>; using pii = pair<int, int>; const int inf = 1e18; const int N = 1e5 + 5; const int mod = 998244353; vector<vector<int>> f(N); vi inv(N); int power( int x , int y ){ int ans = 1; while( y ){ if( y & 1) ans = ans * x % mod; x = x * x % mod , y /= 2; } return ans; } void solve() { int n, k; cin >> n >> k; if (n < k) { cout << "0\n"; } else if (k == 0) { cout << "1\n"; } else { int t = n - k + 1; if (f[k].empty()) f[k].push_back(0), f[k].push_back(2); for (int i = f[k].size() - 1; i <= t; i++) f[k].push_back((2 * k % mod * f[k][i] % mod * inv[i] % mod + f[k][i - 1]) % mod); cout << f[k][t] << "\n"; } return; } int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr); inv[0] = -1; for( int i = 1 ; i < N ; i ++ ) inv[i] = power( i , mod-2); int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

4|0E. 时间超限α


就是求一下前缀的最大值就好了。

#include <bits/stdc++.h> using namespace std; using vi = vector<int>; int main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; int res = 0; vector< vi > a(n+1); for( int i = 1 , x ; i <= n ; i ++ ){ cin >> x; a[i].resize( x + 1 ); for( int j = 1 ; j <= x ; j ++ ) cin >> a[i][j]; } int m; cin >> m; for( int i = 1 ; i <= n ; i ++ ){ for( int j = 1 ; j <= min( m , (int)a[i].size()-1 ) ; j ++ ) res = max( res , a[i][j] ); } cout << res << "\n"; return 0; }

5|0I. 期中考试


模拟一下就好了

#include <bits/stdc++.h> using namespace std; using vi = vector<int>; int main() { ios::sync_with_stdio(false), cin.tie(nullptr); set<int> x; for (int i = 1, v; i <= 3; i++) cin >> v, x.insert(v); int res = 0; int a0, a1, b0, b1; cin >> a0 >> a1 >> b0 >> b1; if (a0 == b0) { for (int i = a1; i < b1; i++) { if (x.count(i) == 0) res++; } } else { for (int i = a1; i <= 7; i++) { if (x.count(i) == 0) res++; } for (int i = 1; i < b1; i++) { if (x.count(i) == 0) res++; } int cnt = 0; for (int i = 1; i <= 7; i++) { if (x.count(i) == 0) cnt++; } for (int i = a0 + 1; i < b0; i++) res += cnt; } cout << res << "\n"; return 0; }

6|0L. 兄弟校问题


首先兄弟学校之间的关系用并查集来维护就好了。

剩下就是如何判断兄弟学校,首先O(n2)的根据城市判断一下。

然后再O(nm)的根据关键字判一下,因为这里面的字符串不太长,我直接截取下来,转成小写字母丢进 set 就好了。

#include <bits/stdc++.h> using namespace std; using vi = vector<int>; #define lowbit(x) ( x & - x ) struct dsu { vi fa; dsu(int n = 1){ fa = vi( n+1 , -1ll ); fa[0] = 0; } int getfa(int x) { if (fa[x] < 0) return x; return fa[x] = getfa(fa[x]); } void merge(int x, int y) { x = getfa(x), y = getfa(y); if (x == y) return; if (fa[x] > fa[y]) swap(x, y); fa[x] += fa[y], fa[y] = x; } int size(int x) { x = getfa(x); return -fa[x]; } }; int main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m; cin >> n >> m; dsu d(n); vector<set<string>> keyWords(n+1); vector<string> city(n+1); auto toLow = [](string s) { for (auto &i: s) if (i >= 'A' and i <= 'Z') i = i + 'a' - 'A'; return s; }; for (int i = 1; i <= n; i++) { string s , t = ""; cin >> s >> city[i]; s += '_'; for ( auto c: s) { if (c == '_') { keyWords[i].insert(toLow(t) ); t = ""; } else t += c; } } for (int i = 1; i <= n; i++) { for (int j = 1; j < i; j++) { if (city[i] != city[j]) continue; d.merge(i, j); } } string key; for (int i = 1, p, q; i <= m; i++) { cin >> key; for (p = 1; p <= n; p++) if (keyWords[p].count(key)) break; for (q = p + 1; q <= n; q++) { if (keyWords[q].count(key)) d.merge(p, q); } } for( int i = 1 ; i <= n ; i ++ ) cout << d.size(i) - 1 << "\n"; return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/17824796.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(110)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2022-11-10 牛客小白月赛 54
2022-11-10 牛客小白月赛55
2021-11-10 2021 ccpc 女生赛部分题解
点击右上角即可分享
微信分享提示