2024“图森未来杯”程序设计邀请赛

https://voj.mobi/contest/242/problems,密码2024ecnutsol

1|0A - 调和与折中


#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using vi = vector<int>; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); i64 a, b, c, d, e, f; cin >> a >> b >> c >> d >> e >> f; if(f * (a * c + b) == c * (d * f + e)) cout << "Yes\n"; else cout << "No\n"; return 0; }

2|0B - 数位游戏


如果x<10 且为奇数,则无解。

否则记cnt=bitcnt(p),如果cnt为偶数,则一定存在一种不进位的方法,则答案为cnt/2,否则存在一种只进一次位的方法,则答案为cnt/2+5

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using vi = vector<int>; void solve(){ string s; cin >> s; if(s.size() < 2 and (s.front() - '0') % 2 == 1) { cout << "-1\n"; return; } int cnt = 0; for(auto i : s) cnt += i - '0'; if(cnt % 2 == 0) cout << cnt / 2 << "\n"; else cout << cnt / 2 + 5 << "\n"; return; } i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for(cin >> TC; TC; TC --) solve(); return 0; }

3|0C - 抽卡与破防


根据题目可以得到出六星的概率

p(x)={a100xnmin(a+(xn)b100,100)x>n

然后可以得到不出六星的概率arcp(x)=1p(x)

对于出六星是 up 的概率是q=c100,歪的概率是arcq=1q

E(i,j)表示从第i抽抽卡开始,累计j抽未出六星是,抽出up的概率是多少

对于没有到达保底的的情况i<m

E(i,j)=1+p(j)×(arcq×E(i+1,0)+q×0)+arcp[j]×E(i+1,j+1)

对于已经到达保底的情况i>m

E(i,j)=1+p(j)×0+arcq(j)×E(i+1,j+1)

然后我们递归加记忆化就可以的了,递归的过程中,如果已经到达保底出六星也就是arcq[j]=0时就不要在搜索E(i+1,j+1)

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int i64 using vi = vector<int>; const int N = 200, M = 20000, mod = 1e9+7; int e[M + 1][N + 1], p[N + 1], arcp[N + 1]; int n, m, a, b, c, q, arcq; int power(int x, int y) { int ans = 1; while(y) { if(y & 1) ans = ans * x % mod; x = x * x % mod; y >>=1; } return ans; } int inv(int x) { return power(x, mod - 2); } void init(){ int inv100 = inv(100); q = c * inv100 % mod; arcq = (100 - c) * inv100 % mod; for(int x = 0; x <= N; x ++){ if(x <= n) p[x] = a * inv100 % mod; else p[x] = min(a + (x - n) * b, 100ll) * inv100 % mod; arcp[x] = (1ll - p[x] + mod) % mod; } for(int i = 0; i <= M; i ++) for(int j = 0; j <= N; j ++) e[i][j] = -1; return; } int E(int i ,int j) { if(e[i][j] != -1) return e[i][j]; if(i < m) { e[i][j] = 1; if(arcp[j] % mod != 0) e[i][j] = (e[i][j] + arcp[j] * E(i + 1, j + 1) % mod) % mod; // 没出六星 e[i][j] = (e[i][j] + p[j] * arcq % mod * E(i + 1 , 0) % mod ) % mod; // 出六星 但不是 up } else { // 出六星必 up e[i][j] = 1; if(arcp[j] % mod != 0) e[i][j] = (e[i][j] + arcp[j] * E(i + 1, j + 1)) % mod; // 没出六星 } assert(e[i][j] >= 0); return e[i][j] %= mod; } i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); cin >> n >> m >> a >> b >> c; init(); cout << E(0, 0); return 0; }

4|0F - 花狮平衡树


想了很久,最后还是用裸的 splay树实现的。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ll = long long; using vi = vector<int>; using pii = pair<int, int>; const int N = 5e5+5; int n; struct Splay { int rt, tot, fa[N], ch[N][2], val[N], cnt[N], siz[N]; int tag[N]; void push_up(int x) { siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x]; } void push_down(int x) { if (x && tag[x]) { if (ch[x][0])tag[ch[x][0]] ^= 1; if (ch[x][1])tag[ch[x][1]] ^= 1; swap(ch[x][0], ch[x][1]); tag[x] = 0; } } bool get(int x) { return x == ch[fa[x]][1]; } void clear(int x) { ch[x][0] = ch[x][1] = fa[x] = val[x] = siz[x] = cnt[x] = 0; } void rotate(int x) { int y = fa[x], z = fa[y], chk = get(x); push_down(x); push_down(y); ch[y][chk] = ch[x][chk ^ 1]; if (ch[x][chk ^ 1]) fa[ch[x][chk ^ 1]] = y; ch[x][chk ^ 1] = y; fa[y] = x; fa[x] = z; if (z) ch[z][y == ch[z][1]] = x; push_up(y); } void splay(int x, int goal) { for (int f = fa[x]; (f = fa[x]) != goal; rotate(x)) if (fa[f] != goal) rotate(get(x) == get(f) ? f : x); if (goal == 0)rt = x; } void splay(int x) { splay(x, 0); } int kth(int k) { int cur = rt; while (1) { push_down(cur); if (ch[cur][0] && k <= siz[ch[cur][0]]) { cur = ch[cur][0]; } else { k -= cnt[cur] + siz[ch[cur][0]]; if (k <= 0) { splay(cur); return cur; } cur = ch[cur][1]; } } } int find(int x) { return kth(x + 1); } int build(int L, int R, int father) { if (L > R) { return 0; } int x = ++tot; int mid = (L + R) / 2; fa[x] = father; cnt[x] = 1; val[x] = mid; ch[x][0] = build(L, mid - 1, x); ch[x][1] = build(mid + 1, R, x); push_up(x); return x; } void rev(int L, int R) { int fl = find(L - 1); int fr = find(R + 1); splay(fl, 0); splay(fr, fl); int pos = ch[rt][1]; pos = ch[pos][0]; tag[pos] ^= 1; } void dfs(int x) { push_down(x); if (ch[x][0])dfs(ch[x][0]); if (val[x] != 0 && val[x] != (n + 1))cout << val[x] << " "; if (ch[x][1])dfs(ch[x][1]); } } tree; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int m; cin >> n >> m; tree.build(0, n + 1 , 0); tree.rt = 1; while(m -- ){ int l , r; cin >> l >> r; tree.rev(l ,r); } tree.dfs(tree.rt); return 0; }

5|0H - 橡木蛋糕卷


首先我们计算出每个传送点到所有的蛋糕店的最短距离,然后就转换成了经典旅行商问题,用状压 dp 来解决。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using ll = long long; using vi = vector<int>; using pii = pair<int, int>; const int N = (1 << 18) + 8; int dx[] = {0,0,-1,1}; int dy[] = {1,-1,0,0}; int stos[20][20]; int dp[N][20]; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n,m;cin >> n >> m; vector<vector<char>> a(n + 1,vector<char>(m + 1)); vector<pair<int,int>> t(1),s(1); for (int i = 1;i <= n;i++){ for (int j = 1;j <= m;j++){ cin >> a[i][j]; if (a[i][j] == 'S') s.push_back({i,j}); if (a[i][j] == 'T') t.push_back({i,j}); } } auto bfs = [&](int sx,int sy)->vector<vector<int>>{ queue<pair<int,int>> q; q.push({sx,sy}); vector<vector<int>> vis(n + 1,vector<int>(m + 1)); vector<vector<int>> d(n + 1,vector<int>(m + 1, 1e9)); d[sx][sy] = 0; vis[sx][sy] = 1; while (!q.empty()){ auto [x,y] = q.front(); q.pop(); for (int i = 0;i < 4;i++){ int u = x + dx[i],v = y + dy[i]; if (u < 1 || v < 1 || u > n || v > m || vis[u][v] || a[u][v] == '#'){ continue; } q.push({u,v}); d[u][v] = d[x][y] + 1; vis[u][v] = 1; } } return d; }; int siz = s.size() - 1; vector<int> ttos(s.size(),1e9); int idx = 0; for( int i = 0 ; i < 20 ; i ++ ) for( int j = 0 ; j < 20 ; j ++ ) stos[i][j] = 1e9; for (int i = 1;i < s.size();i++){ auto [x,y] = s[i]; auto tmp = bfs(x,y); for (int j = 1;j < s.size();j++){ auto [u,v] = s[j]; stos[i][j] = min(stos[i][j],tmp[u][v]); } for (auto [u,v] : t){ ttos[i] = min(ttos[i],tmp[u][v]); } } for (int i = 1;i < (1 << siz);i++){ for (int j = 0;j < 20;j++){ dp[i][j] = 1e9; } } dp[0][0] = 0; for (int i = 1;i < (1 << siz);i++){ for (int j = 1;j <= siz;j++){ if ((i >> (j - 1)) & 1){ // END int tmp = 1e9; for (int k = 1;k <= siz;k++){ // ST if ((i >> (k - 1) )& 1 && k != j){ tmp = min(tmp,dp[i - (1 << (j - 1))][k]); dp[i][j] = min(dp[i][j],dp[i - (1 << (j - 1))][k] + stos[j][k]); } } if (tmp == 1e9) tmp = 0; dp[i][j] = min(dp[i][j],tmp + ttos[j]); } } } int ans = 1e9; for (int i = 1;i <= siz;i++){ ans = min(dp[(1 << siz) - 1][i],ans) ; } cout << ans << endl; return 0; }

__EOF__

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