https://atcoder.jp/contests/abc265
有两种购买策略:\(x\) 元买一个苹果 or \(y\) 元买三个苹果,问买 \(n\) 个苹果最少要花多少钱
#include <bits/stdc++.h> using namespace std; int main () { int x, y, n; cin >> x >> y >> n; if (n < 3 || x * 3 <= y) { cout << x * n << endl; } else { cout << (n/3)*y + (n%3)*x; } }
从 \(i-1\) 走到 \(i\) 点需要消耗 \(a_i\), 有 \(m\) 个点 \(b_i\) 存在补助,初始有 \(t\), 问能不能从 \(1\) 走到 \(n\)
注意先减再添加补助
#include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e5 + 5; int n, m, t; int a[N], b[N]; signed main () { cin >> n >> m >> t; for (int i = 2; i <= n; i++) cin >> a[i]; for (int i = 1; i <= m; i++) { int x, y; cin >> x >> y; b[x] = y; } for (int i = 2; i <= n; i++) { t -= a[i]; if (t <= 0) { cout << "No\n"; return 0; } t += b[i]; } cout << "Yes\n"; } //模拟
有 \(n*m\) 的地图,初始在 \((1,1)\), 规则:\(U\) 向上一格,\(D\) 向下一格,\(R\) 向右一格,\(R\) 向左一格。
问走到哪里时下一步就出界,永不出界输出 \(-1\)
按题意模拟,如果走完了整个地图还不出界,则永不出界。
#include <bits/stdc++.h> using namespace std; const int N = 505; int n, m; char a[N][N]; bool check (int x, int y) { if (x > n || x <= 0 || y > m || y <= 0) return false; return true; } signed main () { cin >> n >> m; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { cin >> a[i][j]; } int x = 1, y = 1, sx, sy; int cnt = n * m; while (1) { cnt --; sx = x, sy = y; if (a[x][y] == 'U') x --; else if (a[x][y] == 'D') x ++; else if (a[x][y] == 'R') y ++; else if (a[x][y] == 'L') y --; if (!check (x, y)) { cout << sx << ' ' << sy; break; } if (cnt <= 0) { cout << -1; break; } //x = sx, y = sy; } } //一直走走到出界
现有一数列 \(A=(A_0,...,A_{N-1})\), 问能不能找到四点 \(x,y,z,w\), 满足:
暴力 \(set\) 查找
#include <bits/stdc++.h> #define int long long using namespace std; const int N = 2e5 + 5; int n, p, q, r; int sum[N]; signed main () { cin >> n >> p >> q >> r; set<int> s; s.insert (0); for (int i = 1; i <= n; i++) { int x; cin >> x; sum[i] = sum[i-1] + x; s.insert (sum[i]); } for (int i = 1; i <= n; i++) { if (s.count (sum[i-1]+p) && s.count (sum[i-1]+p+q) && s.count (sum[i-1]+p+q+r)) { cout << "Yes\n"; return 0; } } cout << "No\n"; } //sum[y-1]-sum[x-1]=p //sum[z-1]-sum[y-1]=q //sum[w-1]-sum[z-1]=r
假设现在在 \((x,y)\), 下一步可以选择走到 \((x+A,y+B)\) or \((x+C,y+D)\) or \((x+E,y+F)\), 且有 \(m\) 个障碍, 问走 \(n\) 步能有多少种可能的路径
定义状态 \(f[i][j][k]:\) 表示 1走了 \(i\) 次,2走了 \(j\) 次,3走了 \(k\) 次。
线性 dp 路径转移即可
#include <bits/stdc++.h> #define int long long using namespace std; typedef pair<int, int> pii; const int N = 305, mod = 998244353; int A, B, C, D, E, F, n, m; int f[N][N][N]; //1走了i次,2走了j次,3走了k次 signed main () { cin >> n >> m >> A >> B >> C >> D >> E >> F; set<pii> s; for (int i = 1; i <= m; i++) { int x, y; cin >> x >> y; s.insert({x, y}); } f[0][0][0] = 1; for (int i = 0; i <= n; i++) for (int j = 0; j <= n - i; j++) for (int k = 0; k <= n - i - j; k++) { int x = i*A + j*C + k*E, y = i*B + j*D + k*F; if (!i && !j && !k) continue; if (s.count ({x, y})) continue; if (i) f[i][j][k] += f[i-1][j][k]; if (j) f[i][j][k] += f[i][j-1][k]; if (k) f[i][j][k] += f[i][j][k-1]; f[i][j][k] %= mod; } int ans = 0; for (int i = 0; i <= n; i++) for (int j = 0; j <= n - i; j++) { ans += f[i][j][n-i-j], ans %= mod; } cout << ans; } //移动n次
题意:有两点 \(p,q\), 各有 \(n\) 个维度,问有多少个点满足到 \(p\) 和 \(q\) 的曼哈顿距离均 \(\leq d\)
分析:可以把这样的点分为两类————在 \(p,q\) 之间的,在 \(p,q\) 外的。
对于在两点之外的 \(x_i\), 每走一格,\(d_{p_i},d_{q_i}\) 都会同时 \(\pm 1\);
对于在两点之间的 \(x_i\), 则是 \(d_{p_i}+d_{q_i}=\) 定值,即 \(d_{p_i}\pm1,d_{q_i}\mp1\)。
由这两种特殊性质得,可以维护矩阵的主对角线和副对角线的前缀和,即可dp 转移
#include <bits/stdc++.h> #define int long long using namespace std; const int N = 1005, M = 105, mod = 998244353; int p[M], q[M], dp[N][N], C[N][N], E[N][N]; int n, d; signed main() { cin >> n >> d; for (int i = 0; i < n; i++) cin >> p[i]; for (int i = 0; i < n; i++) cin >> q[i]; dp[0][0] = 1; for (int k = 0; k < n; k++) { int z = abs(p[k] - q[k]); for (int i = 0; i <= d; i++) for (int j = 0; j <= d; j++) { C[i+1][j+1] = (C[i][j] + dp[i][j]) % mod; //主对角线 E[i+1][j] = (E[i][j+1] + dp[i][j]) % mod; //副对角线 dp[i][j] = (C[i][max(j-z, 0ll)] + C[max(i-z, 0ll)][j]) % mod; int m = max(z - j, 0ll); if (i >= m) dp[i][j] = (dp[i][j] + E[i+1-m][j-z+m]) % mod; if (i >= z) dp[i][j] = (dp[i][j] - E[i-z][j+1] + mod) % mod; } } int ans = 0; for (int i = 0; i <= d; i++) for (int j = 0; j <= d; j++) ans = (ans + dp[i][j]) % mod; cout << ans; }