第十届中国大学生程序设计竞赛 重庆站(CCPC 2024 Chongqing Site)

1|0B. osu!mania


按照题目的公式进行计算,注意四舍五入的精度问题。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ldb = long double; using vi = vector<int>; using pii = pair<int,int>; void solve(){ int ppmax; cin >> ppmax; int a, b, c, d, e, f; cin >> a >> b >> c >> d >> e >> f; ldb acc = (300.0 * a + 300 * b + 200 * c + 100 * d + 50 * e) / (300.0 *(a + b + c + d + e + f)); ldb tpp = (320.0 * a + 300 * b + 200 * c + 100 * d + 50 * e) * 5 * ppmax / (320.0 * (a + b + c + d + e + f)); i64 pp = max(0ll, i64(round(tpp)) - 4ll * ppmax); cout <<fixed << setprecision(2) << acc*100.0 << "% " << pp << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while(T --) solve(); return 0; }

2|0C. 连方


如果第一行第七行都是#,则全部都都是#

如果第一行第七行只有一行都是#,则无解。

否则第二行、第六行对第一行、第七行取反,这样可以把第一行和第七行所有#都联通。

然后再第三行第第五行各找一个之和第二行第六行八联通的点,然后通过第四行联通即可。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ldb = long double; using vi = vector<int>; using pii = pair<int,int>; void solve(){ int n; cin >> n; vector<string> a(7); cin >> a[0] >> a[6]; bool f0 = false, f6 = false; for(auto c : a[0]) f0 |= (c == '.'); for(auto c : a[6]) f6 |= (c == '.'); if(f0 != f6) { cout << "No\n"; return; } cout << "Yes\n"; if(f0 == false) { for(int i = 0; i < 7; i ++) cout << a[0] << "\n"; return; } for(int i = 1; i < 6; i ++) a[i] = string(n, '.'); for(int i = 0; i < n; i ++) if(a[0][i] == '.') a[1][i] = '#'; for(int i = 0; i < n; i ++) if(a[6][i] == '.') a[5][i] = '#'; int l = -1, r = -1; for(int i = 0; i < n and l == -1; i ++) { if(a[1][i] == '#') continue; if(i - 1 >= 0 and a[1][i - 1] == '#') l = i; if(i + 1 < n and a[1][i + 1] == '#') l = i; } for(int i = 0; i < n and r == -1; i ++) { if(a[5][i] == '#') continue; if(i - 1 >= 0 and a[5][i - 1] == '#') r = i; if(i + 1 < n and a[5][i + 1] == '#') r = i; } a[2][l] = a[4][r] = '#'; if(l > r) swap(l, r); if(l == r or l + 1 == r ){ a[3][l] = '#'; } else { for(int i = l + 1; i < r ; i ++) a[3][i] = '#'; } for(int i = 0; i < 7; i ++) cout << a[i] << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while(T --) solve(); return 0; }

3|0D. 有限小数


对于一个分数,如果是有限小数。则分母质因数分解后一定只包含2,5。设w表示为b除了2,5外的质因子乘积。则d=2x5yw。找规律可以发现d一定满足d=2X5Yw的形势。因此有ab+cd=ad+cbbd=k。我们要求的k一定是有限小数,则一定可以表示为k=z2x+X5y+Y,zZ。因此我们只要解出丢番图方程c×bz×w2=a×d的整数解,并求出c的最小正整数解即可。

#include <bits/stdc++.h> using namespace std; using i64 = long long; const i64 MAXN = 1e9; const i64 inf = LLONG_MAX / 2; i64 exgcd(i64 a, i64 b, i64 &x, i64 &y) { if(b == 0){ x = 1, y = 0; return a; } i64 d = exgcd(b, a % b, y, x); y -= a / b * x; return d; } i64 calc(i64 a, i64 b, i64 c) { i64 x, y; i64 d = exgcd(a, b, x, y); if(c % d != 0) return inf; x *= c / d; i64 t = abs(b / d); return (x % t + t) % t; } void solve() { i64 a, b; cin >> a >> b; i64 w = b; while(w % 2 == 0) w /= 2; while(w % 5 == 0) w /= 5; if(w == 1) { cout << "0 1\n"; return; } i64 resc = inf, resd; for(i64 p5 = w; p5 <= MAXN; p5 *= 5) for(i64 d = p5, c; d <= MAXN; d *= 2) { c = calc(b, w * w, - a * d); if(c < resc) resc = c, resd = d; } cout << resc << " " << resd << "\n"; return; } int main() { int T; cin >> T; while(T --) solve(); return 0; }

4|0E. 合成大西瓜


对于度为1的点,只能是x,z。因此能保存下的只有可能是次大值。否则,则可以是x,y,z,一定可以保存下最大值。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using vi = vector<int>; using pii = pair<int,int>; const int inf = INT_MAX / 2; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m; cin >> n >> m; vi a(n + 1); for(int i = 1; i <= n; i ++) cin >> a[i]; vi deg(n + 1); for(int x, y; m; m --) { cin >> x >> y; deg[x] ++, deg[y] ++; } int leaf1 = -inf, leaf2 = -inf, node = -inf; for(int i = 1; i <= n; i ++) { if(deg[i] == 1) { if(a[i] > leaf1) leaf2 = leaf1, leaf1 = a[i]; else leaf2 = max(leaf2, a[i]); } else node = max(node, a[i]); } if(leaf2 == -inf) cout << node << "\n"; else if(node == -inf) cout << leaf2 << "\n"; else cout << max(node, leaf2); return 0; }

5|0I. 算术


对于任意的两个数x,y,如果满足1<x,y,则一定有xyx+y。因为求和操作一定是至少有一个数为1

这样的话,考虑把卡牌分成若干组,每一组内求和,组之间求积。我们可以给每一组先分配一张卡牌,然后再给某些组进行加一。

因为一个组内不能有两个大于一的数,因此组个数的变化实际上只受到了1的影响。因此我们可以枚举有多少个1作为一组。

然后我们考虑,如果x<y,则一定有(x+1)y=xy+y>xy+x=x(y+1)。因此加一操作应是对最小的组最优。我们用优先队列维护每组的和,每次对最小的组加一即可。

考虑不同的分组方案如何比较,比较乘积无法实现,但是可以比较乘积的对数。

这样的话,完全没有分类讨论。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ldb = long double; #define int i64 using vi = vector<int>; using pii = pair<int,int>; const int mod = 998244353; void solve() { vi a(10); for(int i = 1; i <= 9; i ++) cin >> a[i]; vi res; ldb val = 0; for(int i = 0; i <= a[1]; i ++) { priority_queue<int,vi,greater<>> heap; for(int j = 0; j < i; j ++) heap.push(1); for(int j = 2; j <= 9; j ++) for(int k = 0; k < a[j]; k ++) heap.push(j); if(heap.empty()) continue; int x = a[1] - i; while(x --) { int y = heap.top(); heap.pop(); heap.push(y + 1); } vi ret; ldb ans = 0; while(not heap.empty()) { ret.push_back((i64)heap.top()), ans += log((i64)heap.top()); heap.pop(); } if(ans > val) res = ret, val = ans; } int pi = 1; for(auto i : res) pi = pi * i % mod; cout << pi << "\n"; return ; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while(T --) solve(); return 0; }

6|0J. 骰子


观察题目,首先起始状态底面为6。观察样例,样例证明了存在一种方案可以使得右侧第一格和下边第一个底面为6。因此一定有一种方法可以使得每一格都是6

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using vi = vector<int>; using pii = pair<int,int>; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); i64 n, m; cin >> n >> m; cout << n * m * 6ll << "\n"; return 0; }

7|0K. 小 C 的神秘图形


观察生成图案的方法。如果坐标的最高位都不是1,则为0。否则可以递归询问。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using vi = vector<int>; using pii = pair<int,int>; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; string x, y; cin >> x >> y; ranges::reverse(x), ranges::reverse(y); while(true){ if((x.back() == '1') or (y.back() == '1')) { if(n == 1) { cout << 1 << "\n"; return 0; } else { x.pop_back(), y.pop_back(), n --; } }else { cout << 0 << "\n"; return 0; } } return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/18544241.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(501)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2023-11-13 AtCoder Beginner Contest 323
点击右上角即可分享
微信分享提示