AtCoder Beginner Contest 129 解题报告
Posted mrzdtz220
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 129 解题报告相关的知识,希望对你有一定的参考价值。
写了四个题就跑去打球了。第五题应该能肝出来的。
#include <bits/stdc++.h> using namespace std; inline int read() int x = 0, f = 1; char ch = getchar(); while (ch < ‘0‘ || ch > ‘9‘) if (ch == ‘-‘) f = -1; ch = getchar(); while (ch >= ‘0‘ && ch <= ‘9‘) x = x * 10 + ch - 48; ch = getchar(); return x * f; int main() int a = read(), b = read(), c = read(); int ans = 1e9; ans = min(ans, a + b); ans = min(b + c, ans); ans = min(ans, c + a); cout << ans << ‘\n‘; return 0;
看错题意了。。改的时候就直接暴力了一发。。
#include <bits/stdc++.h> using namespace std; inline int read() int x = 0, f = 1; char ch = getchar(); while (ch < ‘0‘ || ch > ‘9‘) if (ch == ‘-‘) f = -1; ch = getchar(); while (ch >= ‘0‘ && ch <= ‘9‘) x = x * 10 + ch - 48; ch = getchar(); return x * f; const int N = 110; int a[N], sum[N]; int main() int n = read(); for (int i = 1; i <= n; i++) a[i] = read(); for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i]; int ans = 1e9; for (int T = 1; T < n; T++) int sum0 = 0; for (int i = 1; i <= n; i++) if (i <= T) sum0 += a[i]; else break; ans = min(ans, abs(sum[n] - sum0 - sum0)); // printf("%d\n", ans); printf("%d\n", ans); return 0;
题意:走台阶,一次走一至两个台阶,有些台阶是坏的,问走到第$n$个台阶的方案数
思路:就是普通的递推,坏的台阶$f[i]$设为0
#include <bits/stdc++.h> #define ll long long using namespace std; inline int read() int x = 0, f = 1; char ch = getchar(); while (ch < ‘0‘ || ch > ‘9‘) if (ch == ‘-‘) f = -1; ch = getchar(); while (ch >= ‘0‘ && ch <= ‘9‘) x = x * 10 + ch - 48; ch = getchar(); return x * f; const int N = 1e5 + 10; const ll mod = 1e9 + 7; bool vis[N]; ll f[N]; int main() int n = read(), m = read(); while (m--) int x = read(); vis[x] = 1; f[0] = 1; if (!vis[1]) f[1] = 1; for (int i = 2; i <= n; i++) if (vis[i]) continue; f[i] = (f[i - 1] + f[i - 2]) % mod; printf("%lld\n", f[n]); return 0;
题意:一个网格,有些地方是墙,问在哪个没有墙的地方放个灯,灯能照射的范围最远,灯能往上下左右延伸
思路:刚开始傻逼傻逼的对每个点往四个方向延伸,然后就获得了一个TLE。从左上对每个点统计从它的左方和上方分别能走多远,从右下对每个点统计从它的右方和下方分别能走多远
然后再对每一个点求一边四个方向的和的最大值
#include <bits/stdc++.h> using namespace std; inline int read() int x = 0, f = 1; char ch = getchar(); while (ch < ‘0‘ || ch > ‘9‘) if (ch == ‘-‘) f = -1; ch = getchar(); while (ch >= ‘0‘ && ch <= ‘9‘) x = x * 10 + ch - 48; ch = getchar(); return x * f; const int N = 2020; char s[N][N]; int dp[N][N][4]; int main() int n = read(), m = read(); for (int i = 0; i < n; i++) scanf("%s", s[i]); int ans = 0; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) if (s[i][j] == ‘.‘) dp[i][j][0] = dp[i][j][1] = 1; if (j > 0 && dp[i][j - 1][0] > 0) dp[i][j][0] = dp[i][j - 1][0] + 1; if (i > 0 && dp[i - 1][j][1] > 0) dp[i][j][1] = dp[i - 1][j][1] + 1; for (int i = n - 1; i >= 0; i--) for (int j = m - 1; j >= 0; j--) if (s[i][j] == ‘.‘) dp[i][j][2] = dp[i][j][3] = 1; if (j < m - 1 && dp[i][j + 1][2] > 0) dp[i][j][2] = dp[i][j + 1][2] + 1; if (i < n - 1 && dp[i + 1][j][3] > 0) dp[i][j][3] = dp[i + 1][j][3] + 1; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) if (s[i][j] == ‘#‘) continue; int temp = 1; for (int cnt = 0; cnt < 4; cnt++) temp += dp[i][j][cnt]; ans = max(ans, temp - 4); printf("%d\n", ans); return 0;
题意:给一个二进制数$L$,问有多少对$\left(a,b\right)$满足:$a+b \leq L$ $a+b = a \oplus b$
思路:为啥别人看到都直接莽DP啊,为啥我看到就推公式啊。因为第二个条件,对于每一位 $a$和$b$只能为$\left(0,0\right)$ $\left(1,0\right)$ $\left(0, 1\right)$ 三种情况
所以如果给出的$L$是全1,那么答案就是$3^len$,但是由于第一个条件存在,那么对于每一位为0的,不能出现 1.比他高位的1的位置出现 $\left(1,0\right)$ $\left(0, 1\right)$ 2.这个位置出现$\left(1,0\right)$ $\left(0, 1\right)$ 那么就用一个系数$c$来保存1位置,每到一个1位置, $c$乘2,每到一个0位置,答案减去 $c \times 3 ^x$ $x$是这个位置往后的数的长度 就是前面1位置出现了一个为0一个为1 这个0位置出现一个0一个为1 $a + b$就会大于$L$ 那么后面的随机组合的情况就是多出来了 所以减去就完了。
代码里面还有一个是DP的,我是拿来对拍的...
#include <bits/stdc++.h> #define ll long long using namespace std; const ll mod = 1e9 + 7; ll qp(ll a, ll b) ll res = 1; while (b) if (b & 1) res = res * a % mod; a = a * a % mod; b >>= 1; return res; const int N = 1e5 + 10; char s[N]; ll dp[N]; ll bit[N]; int main() scanf("%s", s); int len = strlen(s); ll ans = qp(3, len); bit[0] = 1; for (int i = 1; i <= len; i++) bit[i] = bit[i - 1] * 3 % mod; if (s[0] == ‘0‘) ans = (ans - 2 * qp(3, len - 1)) % mod; ll temp = 4; for (int i = 1; i < len; i++) if (s[i] == ‘0‘) ans = (ans - temp * bit[len - i - 1] % mod + mod) % mod; else temp = temp * 2 % mod; // dp[0] = 1; // reverse(s, s + len); // for (int i = 0; i < len; i++) // if (s[i] == ‘1‘) dp[i + 1] = (2 * dp[i] + bit[i]) % mod; // else dp[i + 1] = dp[i]; // printf("%lld\n", ans); return 0;
F - Takahashi‘s Basics in Education and Learning
题意:给一个等差数列的首项和公差和项数,把这$L$项给拼起来,问最后这个大数模$M$的答案是多少
思路:完全没明白咋写...看了别人的代码看半天才懂...
这个大数的组成就是$a_0\times 10^b_0\cdot +a_1\times 10^b_1+\ldots +a_L - 1\times 10^b_L - 1$
答案把这$L$项按他们的长度分类 然后对于每一个构造一个矩阵
$\beginpmatrix bit & 1 & 0 \\ 0 & 1 & d \\ 0 & 0 & 1 \endpmatrix$
答案矩阵为$\beginpmatrix ans \\ a_st \\ 1 \endpmatrix$
找到$a_st$二分就OK了
学习了。
#include <bits/stdc++.h> #define ll long long using namespace std; inline ll read() ll x = 0, f = 1; char ch = getchar(); while (ch < ‘0‘ || ch > ‘9‘) if (ch == ‘-‘) f = -1; ch = getchar(); while (ch >= ‘0‘ && ch <= ‘9‘) x = x * 10 + ch - 48; ch = getchar(); return x * f; ll mod; struct M ll a[3][3]; ; M operator * (const M &a, const M &b) M c; for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) c.a[i][j] = 0; for (int k = 0; k < 3; k++) c.a[i][j] = (c.a[i][j] + a.a[i][k] * b.a[k][j] % mod) % mod; return c; M qp(M a, ll b) M c; for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) c.a[i][j] = i == j; while (b) if (b & 1) c = c * a; a = a * a; b >>= 1; return c; int main() ll n = read(), a0 = read(), d = read(); mod = read(); ll bit = 10, ans = 0; ll st = 0; for (int i = 1; i <= 19; i++) ll l = st, r = n, p = -1; while (l + 1 < r) ll mid = l + r >> 1; if (mid * d + a0 < bit) l = mid , p = mid; else r = mid; if (l * d + a0 < bit) p = l; if (p != -1) M a; a.a[0][0] = bit % mod; a.a[0][1] = a.a[1][1] = a.a[2][2] = 1LL; a.a[0][2] = a.a[1][0] = a.a[2][0] = a.a[2][1] = 0LL; a.a[1][2] = d % mod; a = qp(a, p - st + 1); ll ast = a0 % mod + d % mod * st % mod; ast %= mod; ans = (ans * a.a[0][0] % mod + ast * a.a[0][1] % mod + a.a[0][2] % mod) % mod; st = p + 1; if (st >= n) break; bit *= 10; printf("%lld\n", ans); return 0;
以上是关于AtCoder Beginner Contest 129 解题报告的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解