AtCoder Beginner Contest 132 解题报告
Posted mrzdtz220
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 132 解题报告相关的知识,希望对你有一定的参考价值。
前四题都好水。后面两道题好难。
#include <cstdio> #include <algorithm> 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; int a[N]; int main() int n = read(); for (int i = 0; i < n; i++) a[i] = read(); sort(a, a + n); printf("%d\n", a[n / 2] - a[n / 2 - 1]); return 0;
#include <cstdio> 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 MOD = 1e9 + 7; const int N = 2010; int C[N][N]; void init() C[0][0] = 1; C[1][0] = C[1][1] = 1; for (int i = 2; i < N; i++) C[i][0] = 1; for (int j = 1; j <= i; j++) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD; int main() init(); int n = read(), k = read(); for (int i = 1; i <= k; i++) printf("%d\n", 1LL * C[k - 1][i - 1] * C[n - k + 1][i] % MOD); return 0;
题意:给一个有向图,问能不能从$S$,走$3^x$ $x \geq 1$ 能输出$x$,不能输出-1
思路:BFS。刚开始想的是对每一个点,枚举它往后走三步的点,但是T了。正解应该用$dis\left[ i\right] \left[ k\right]$表示走到$i$,并且走的步数模3等于$k$ 然后BFS就OK了。
#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 = 1e5 + 10; const int INF = 0x3f3f3f3f; int n, m, s, t, dis[N][3]; vector<int> G[N]; void bfs() memset(dis, -1, sizeof(dis)); dis[s][0] = 0; queue< pair<int, int> > que; que.push(s, 0); while (!que.empty()) pair<int, int> u = que.front(); que.pop(); for (auto v : G[u.first]) if (dis[v][(u.second + 1) % 3] < 0) dis[v][(u.second + 1) % 3] = dis[u.first][u.second] + 1; que.push(v, (u.second + 1) % 3); int main() n = read(), m = read(); while (m--) int u = read(), v = read(); G[u].push_back(v); s = read(), t = read(); bfs(); if (dis[t][0] == -1) puts("-1"); else printf("%d\n", dis[t][0] / 3); return 0;
题意:给定一个$N$,$K$,问长度为$K$,且相邻两数的乘积不超过$N$的方案数。
思路:我只会$O\left( KN^2\right)$的暴力。看了题解瞬间觉得...tql
将数分为小于等于$\sqrt N$和大于$\sqrt N$,记为$s$和$b$
把$b$分成$\sqrt N$块 第$i$块表示$i\cdot b\leq N$ 那么这个块里有$\dfrac Ni-\dfrac Ni+1$个数
$S\left( i,j\right)$表示长度为$i$,最后一个数为$j$ ($j\leq \sqrt N$)的方案数
$B\left( i,j\right)$表示长度为$i$,最后一个数在块$B^j$里($j\leq \sqrt N$)的方案数
一个小的数前面可以放任意一个小的数,也可以放一个大数,这个数与这个小的数乘积小于等于$N$
那么$S$的递推式子是$S\left( i,j\right) =\sum ^\sqrt N_k=1s\left( i-1,k\right) +\sum ^\sqrt N_k=jB\left( i-1,k\right)$
$B$的递推式子是$B\left( i,j\right) =\left( \dfrac Nj-\dfrac Nj+1\right) \sum ^j_k=1S\left( i-1,k\right)$
$ans=\sum ^\sqrt N_i=1\left( S\left( k,i\right) +B\left( k,i\right) \right)$
但是这样复杂度是$O\left( k\left( \sqrt N\right) ^2\right)$
在计算的过程中计算完这一层可以把这一层的给求个和,复杂度就降为$O\left( k\sqrt N\right)$
好题。
#include <cstdio> #include <cstring> #include <cmath> #define ll long long using namespace std; const ll MOD = 1e9 + 7; const int N = 5e4 + 10; ll S[110][N], B[110][N]; 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 n = read(), k = read(); int r = sqrt(n) + 1; S[0][1] = 1; for (int i = 0; i < k; i++) for (int j = 1; j < r; j++) S[i][j] = (S[i][j] + S[i][j - 1]) % MOD; for (int j = r - 2; j > 0; j--) B[i][j] = (B[i][j] + B[i][j + 1]) % MOD; for (int j = 1; j < r; j++) B[i + 1][j] = S[i][j] * (n / j - n / (j + 1)); if (j == n / j) B[i + 1][j] = 0; //已被包含在S里 B[i + 1][j] %= MOD; for (int j = 1; j < r; j++) S[i + 1][j] = B[i][j] + S[i][r - 1]; S[i + 1][j] %= MOD; ll ans = 0; for (int i = 1; i <= r; i++) ans = (ans + B[k][i] + S[k][i]) % MOD; printf("%lld\n", ans); return 0;
以上是关于AtCoder Beginner Contest 132 解题报告的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解