A. Welcome to AtCoder Land
模拟
B. Ticket Counter
模拟
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, a;
cin >> n >> a;
vector<int> t(n);
rep(i, n) cin >> t[i];
int x = 0;
rep(i, n) {
if (t[i] < x) {
x += a;
}
else {
x = t[i]+a;
}
cout << x << '\n';
}
return 0;
}
C. Popcorn
先把每条信息压成一个二进制数,再做二进制枚举即可
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<string> s(n);
rep(i, n) cin >> s[i];
using BS = bitset<10>;
vector<BS> b(n);
rep(i, n) {
rep(j, m) if (s[i][j] == 'o') b[i][j] = 1;
}
int ans = n;
rep(x, 1<<n) {
BS bx(x);
BS sb;
rep(i, n) if (bx[i]) sb |= b[i];
if (sb.count() == m) ans = min(ans, (int)bx.count());
}
cout << ans << '\n';
return 0;
}
D. Souvenirs
贪心
先对序列 \(B\) 做升序排序,然后购买当前剩下的数中大于等于 \(B_i\) 的最小值
可以用 std::multiset
来维护序列 \(A\)
也可以用双指针,但需要先对序列 \(A\) 做排序
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int n, m;
cin >> n >> m;
vector<int> a(n), b(m);
rep(i, n) cin >> a[i];
rep(i, m) cin >> b[i];
sort(b.begin(), b.end());
multiset<int> s(a.begin(), a.end());
ll ans = 0;
rep(i, m) {
auto it = s.lower_bound(b[i]);
if (it == s.end()) {
puts("-1");
return 0;
}
ans += *it;
s.erase(it);
}
cout << ans << '\n';
return 0;
}
E. Alphabet Tiles
原题:ABC234F
记 dp[i][j]
表示用前 \(i\) 种大写字母能构成的长度为 \(j\) 的本质不同的字符串个数
代码实现
#include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using mint = modint998244353;
struct modinv {
int n; vector<mint> d;
modinv(): n(2), d({0,1}) {}
mint operator()(int i) {
while (n <= i) d.push_back(-d[mint::mod()%n]*(mint::mod()/n)), ++n;
return d[i];
}
mint operator[](int i) const { return d[i];}
} invs;
struct modfact {
int n; vector<mint> d;
modfact(): n(2), d({1,1}) {}
mint operator()(int i) {
while (n <= i) d.push_back(d.back()*n), ++n;
return d[i];
}
mint operator[](int i) const { return d[i];}
} facts;
struct modfactinv {
int n; vector<mint> d;
modfactinv(): n(2), d({1,1}) {}
mint operator()(int i) {
while (n <= i) d.push_back(d.back()*invs(n)), ++n;
return d[i];
}
mint operator[](int i) const { return d[i];}
} ifacts;
mint comb(int n, int k) {
if (n < k || k < 0) return 0;
return facts(n)*ifacts(k)*ifacts(n-k);
}
int main() {
int n = 26;
int k;
cin >> k;
vector<int> c(n);
rep(i, n) cin >> c[i];
vector<mint> dp(k+1);
dp[0] = 1;
rep(i, n) {
vector<mint> old(k+1);
swap(dp, old);
rep(j, k+1) {
rep(a, c[i]+1) {
int nj = j+a;
if (nj > k) break;
dp[nj] += old[j]*comb(nj, a);
}
}
}
mint ans;
rep(i, k) ans += dp[i+1];
cout << ans.val() << '\n';
return 0;
}
注意到相同元素之间不需要排序,所以可以在原dp的基础上加上除序的操作,也就是 dp[nj] += old[j]/a!;
那么最后的答案就是 \(\sum\limits_{i=1}^k dp[i] \times i!\)
代码实现
#include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using mint = modint998244353;
struct modinv {
int n; vector<mint> d;
modinv(): n(2), d({0,1}) {}
mint operator()(int i) {
while (n <= i) d.push_back(-d[mint::mod()%n]*(mint::mod()/n)), ++n;
return d[i];
}
mint operator[](int i) const { return d[i];}
} invs;
struct modfact {
int n; vector<mint> d;
modfact(): n(2), d({1,1}) {}
mint operator()(int i) {
while (n <= i) d.push_back(d.back()*n), ++n;
return d[i];
}
mint operator[](int i) const { return d[i];}
} facts;
struct modfactinv {
int n; vector<mint> d;
modfactinv(): n(2), d({1,1}) {}
mint operator()(int i) {
while (n <= i) d.push_back(d.back()*invs(n)), ++n;
return d[i];
}
mint operator[](int i) const { return d[i];}
} ifacts;
mint comb(int n, int k) {
if (n < k || k < 0) return 0;
return facts(n)*ifacts(k)*ifacts(n-k);
}
int main() {
int n = 26;
int k;
cin >> k;
vector<int> c(n);
rep(i, n) cin >> c[i];
vector<mint> dp(k+1);
dp[0] = 1;
rep(i, n) {
vector<mint> old(k+1);
swap(dp, old);
rep(j, k+1) {
rep(a, c[i]+1) {
int nj = j+a;
if (nj > k) break;
dp[nj] += old[j]*ifacts(a);
}
}
}
mint ans;
rep(i, k) ans += dp[i+1]*facts(i+1);
cout << ans.val() << '\n';
return 0;
}
F. Easiest Maze
有解的条件:\(N \leqslant K \leqslant NM\) 且 \(K\) 的奇偶性和 \(N\) 的奇偶性相同
关于构造可以参考官方题解的图
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, m, k;
cin >> n >> m >> k;
if (k < n or (k-n)%2 != 0) {
puts("No");
return 0;
}
vector<string> s(n*2+1, string(m*2+1, '+'));
rep(i, n)rep(j, m) s[i*2+1][j*2+1] = 'o';
s[0][m*2-1] = 'S';
s.back()[m*2-1] = 'G';
rep(i, n)rep(j, m-1) s[i*2+1][j*2+2] = '|';
rep(i, n-1)rep(j, m) s[i*2+2][j*2+1] = '-';
rep(i, n-1) s[i*2+2][m*2-1] = '.';
k -= n;
for (int i = 0; i < n-1; i += 2) {
for (int j = m-1; j >= 1; --j) {
if (k > 0) {
s[i*2+2][j*2+1] = '-';
s[i*2+2][j*2-1] = '.';
s[i*2+1][j*2] = '.';
s[i*2+3][j*2] = '.';
k -= 2;
}
}
}
if (n%2 == 1) {
for (int j = 0; j < m-2; j += 2) {
if (k > 0) {
s[n*2-3][j*2+2] = '|';
s[n*2-1][j*2+2] = '.';
s[n*2-2][j*2+1] = '.';
s[n*2-2][j*2+3] = '.';
k -= 2;
}
}
}
puts("Yes");
rep(i, s.size()) cout << s[i] << '\n';
return 0;
}
G. AtCoder Tour
尽可能在 \(k\) 步以内走到尽可能大的格子,如果步数还有剩余就一直停留在原地,容易想到在到达最大值的格子之前不会在路径上某个格子做停留,因为这样会更劣
记 dp[i][j][l]
表示到 \((i, j)\) 为止已经走了 \(l\) 步时的最大愉悦值
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
const int di[] = {-1, 0, 1, 0};
const int dj[] = {0, 1, 0, -1};
inline void chmax(ll& a, ll b) { if (a < b) a = b; };
int main() {
int h, w, k;
cin >> h >> w >> k;
int si, sj;
cin >> si >> sj;
si--; sj--;
vector a(h, vector<int>(w));
rep(i, h)rep(j, w) cin >> a[i][j];
int hw = h*w;
const ll INF = 1e18;
vector dp(hw, vector(h, vector<ll>(w, -INF)));
dp[0][si][sj] = 0;
rep(l, hw-1)rep(i, h)rep(j, w) {
rep(v, 4) {
int ni = i+di[v], nj = j+dj[v];
if (ni<0 or nj<0 or ni>=h or nj>=w) continue;
chmax(dp[l+1][i][j], dp[l][ni][nj]+a[i][j]);
}
}
ll ans = 0;
rep(l, hw)rep(i, h)rep(j, w) {
if (l > k) continue;
ll now = ll(k-l)*a[i][j] + dp[l][i][j];
chmax(ans, now);
}
cout << ans << '\n';
return 0;
}