358
A - Welcome to AtCoder Land
请判断
void solve() {
string s, t;cin >> s >> t;
if (s == "AtCoder" && t == "Land") {
cout << "Yes\n";
} else {
cout << "No\n";
}
}
B - Ticket Counter
在 AtCoder 乐园的入口处,有一个售票亭,游客在此排队逐个购票。每个人的购票过程需要
目前,售票点没有人排队,
对于每个
#define int long long
void solve() {
int n, a;cin >> n >> a;
int pre = 0;
for (int i = 0; i < n; i++) {
int t;cin >> t;
int ans = max(pre, t) + a;
cout << ans << '\n';
pre = ans;
}
}
C - Popcorn
在 AtCoder 乐园里,有
高桥获得了关于每个摊位出售哪些口味爆米花的信息。这些信息由长度为
高桥想尝遍所有口味的爆米花,但又不想走动太多。求高桥至少要去多少个摊位才能买到所有口味的爆米花?
根据数据量,直接二进制枚举即可。
void solve() {
int n, m;cin >> n >> m;
vector<string> s(n);
for (int i = 0;i < n;i++) {
cin >> s[i];
}
int ans = 1e9;
for (int i = 1;i < (1 << n);i++) {
vector<int> vis(m);
for (int j = 0;j <= __lg(i);j++) {
if (((i >> j) & 1)) {
for (int k = 0;k < m;k++) {
if (s[j][k] == 'o') {
vis[k] = 1;
}
}
}
}
int ok = 1;
for (int j = 0;j < m;j++) {
if (!vis[j])ok = 0;
}
if (ok)ans = min(ans, __builtin_popcount(i));
}
cout << ans << '\n';
}
D - Souvenirs
AtCoder 乐园的一家纪念品商店出售
这些盒子的编号为
高桥想从
在这里,他想买的盒子要满足以下条件:
- 对于每个
人, 都能得到至少装有 粒糖果的盒子。
请注意,不允许给一个人多个盒子,也不允许给多个人同一个盒子。
求是否可能买到满足条件的
D 题最简单的一次,双指针即可。
#define int long long
void solve() {
int n, m;cin >> n >> m;
vector<int> a(n + 1), b(m + 1);
for (int i = 1;i <= n;i++)cin >> a[i];
for (int i = 1;i <= m;i++)cin >> b[i];
sort(a.begin() + 1, a.end());
sort(b.begin() + 1, b.end());
int sum = 0, j = 1;
for (int i = 1;i <= n && j <= m;i++) {
if (a[i] >= b[j]) {
sum += a[i];j++;
}
}
if (j <= m) {
cout << "-1\n";return;
}
cout << sum << '\n';
}
E - Alphabet Tiles
求长度在
- 对于满足
的每个整数 ,下面的条件都成立: 满足 a[i] = 'a' + i - 1
- 字符串中
的出现次数介于区间 。
Solution
DP+组合数, 是个原题:ABC234_F
典 ——和 P1077 摆花基本一样
转移方程:
前
种字母长度为 的字符串可以由前 种字母长度为 的字符串加上 个该字符转移而来,而每种可以转移过来的方式有多种(在长度为 的字符串种有 个该字符可以任意调换位置,方案数 )
#define int long long
constexpr int mod = 998244353;
int a[27], f[27][1010], c[1010][1010];
void solve() {
int n;cin >> n;
for (int i = 1;i <= 26;i++)cin >> a[i];
for (int i = 0;i <= n;i++)c[i][0] = 1, c[i][1] = i;
for (int i = 2;i <= n;i++) {
for (int j = 2;j <= n;j++) {
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];c[i][j] %= mod;
}
}
f[0][0] = 1;
for (int i = 1;i <= 26;i++) {
for (int j = 0;j <= n;j++) {
for (int k = 0;k <= min(a[i], j);k++) {
f[i][j] += f[i - 1][j - k] * c[j][k];f[i][j] %= mod;
}
}
}
int ans = 0;
for (int i = 1;i <= n;i++) {
ans += f[26][i];ans %= mod;
}
cout << ans << '\n';
}
斯努克计划在 AtCoder 乐园建造一个迷宫作为新景点。迷宫是一个有
他喜欢简单的迷宫,因此他希望从入口到出口的路径正好经过
例如,在下图中,
下面是一个正式的说明。
有一个网格,网格中有
考虑一个有
个顶点的无向图 。 的每个顶点都由一对整数 唯一标注。两个不同的顶点 和 由一条边连接,当且仅当 和网格上对应的单元格 和 之间没有墙。 条件:存在一条顶点为
的简单路径连接两个顶点 和 ,且包含顶点 和 的连通部分仅由该路径组成。
G - AtCoder Tour
AtCoder Land 由一个网格表示,网格中有
高桥从
- 他要么停留在当前单元格,要么移动到相邻单元格。在此操作之后,如果他位于
单元格,他将获得 的趣味值。
请找出他能获得的最大总乐趣值。
Solution
时间复杂度:
#define int long long
int dx[] = {1, 0, -1, 0, 0};
int dy[] = {0, 1, 0, -1, 0};
void solve() {
int n, m, K;
cin >> n >> m >> K;
int Si, Sj;
cin >> Si >> Sj;
Si--;
Sj--;
vector<vector<int>> A(n, vector<int>(m));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> A[i][j];
}
}
int N = min(n * m, K);
vector<vector<vector<int>>> dp(N + 1, vector<vector<int>>(n, vector<int>(m, INT_MIN)));
dp[0][Si][Sj] = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < m; k++) {
for (int l = 0; l < 5; l++) {
int x = j + dx[l];
int y = k + dy[l];
if (0 <= x && x < n && 0 <= y && y < m) {
dp[i + 1][x][y] = max(dp[i + 1][x][y], dp[i][j][k] + A[x][y]);
}
}
}
}
}
int ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
ans = max(ans, dp[N][i][j] + (K - N) * A[i][j]);
}
}
cout << ans << '\n';
}