358

A - Welcome to AtCoder Land

请判断 S 是否为 "AtCoder"。 T 是否为"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 乐园的入口处,有一个售票亭,游客在此排队逐个购票。每个人的购票过程需要 A 秒。一旦排在队伍前面的人完成购票,下一个人(如果有的话)就会立即开始他们的购票过程。

目前,售票点没有人排队, N 人会陆续前来购票。具体地说, i 这个人将在 Ti 秒后到达售票点。如果已经有人排队,他们会排在队伍的最后;如果没有,他们会立即开始购票。这里, T1<T2<<TN .

对于每个 i (1iN) ,确定从现在起 i /th 的人将在多少秒后完成购票。

#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 乐园里,有 N 个爆米花摊位,编号从 1N 。它们有 M 种不同口味的爆米花,标号为 1,2,,M ,但并不是每个摊位都出售所有口味的爆米花。1N,M10

高桥获得了关于每个摊位出售哪些口味爆米花的信息。这些信息由长度为 MN 字符串 S1,S2,,SN 表示。如果 Sij 个字符是 "o",则表示 i 摊位出售 j 口味的爆米花。如果是 "x",则表示 i 号摊位不出售 j 口味的爆米花。每个摊位至少出售一种口味的爆米花,每种口味的爆米花至少在一个摊位上出售。

高桥想尝遍所有口味的爆米花,但又不想走动太多。求高桥至少要去多少个摊位才能买到所有口味的爆米花?

根据数据量,直接二进制枚举即可。

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 乐园的一家纪念品商店出售 N 盒子。

这些盒子的编号为 1N ,盒子 i 的价格为 Ai 日元,里面有 Ai 块糖果。

高桥想从 N 盒中买 M 盒,然后送给 1,2,,MM 人每人一盒。

在这里,他想买的盒子要满足以下条件:

请注意,不允许给一个人多个盒子,也不允许给多个人同一个盒子。

求是否可能买到满足条件的 M 盒,如果可能,求高桥需要支付的最小总金额。

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

求长度在 [1,k] 之间的由大写英文字母组成的字符串中,满足以下条件的字符串的个数 (模为 998244353 ):

1K1000,0Ci1000

Solution

DP+组合数, 是个原题:ABC234_F

典 ——和 P1077 摆花基本一样

dpi,j 代表使用前 i 种字母,已经组成了长度为 j 的字符串的方案数。

转移方程:dpi,j=k=0min(ci,j)dpi1,jk×(jk)

i 种字母长度为 j 的字符串可以由前 i1 种字母长度为 jk 的字符串加上 k 个该字符转移而来,而每种可以转移过来的方式有多种(在长度为 j 的字符串种有 k 个该字符可以任意调换位置,方案数 (jk))

#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';
}

G - AtCoder Tour

AtCoder Land 由一个网格表示,网格中有 H 行和 W 列。让 (i,j) 表示第 i 行和第 j 列上的单元格。

高桥从 (Si,Sj) 单元格开始,重复下面的操作 K 次:

请找出他能获得的最大总乐趣值。

Solution

dpop,i,j=max(dpop,i,j,dpop1,prei,prej+Ai,j)
时间复杂度:O(n2m2)

#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';
}