Educational Codeforces Round 116 (Rated for Div. 2)ABCDE题解

比赛地址Educational Codeforces Round 116 (Rated for Div. 2)

A. AB Balance

容易看出,直接判断首尾字母是否相同即可,因为最后要化成 aba...a 或者 bab...b 形式才行

#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}

inline void solve() {
    string s; cin >> s;
    s[0] = s[s.size() - 1];
    cout << s << endl;
}
int main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto now = clock();
#endif
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(2);
    int T; cin >> T;
    while (T -- )
        solve();
#ifdef DEBUG
    cout << "============================" << endl;
    cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
    return 0;
}

B. Update Files

根据题意模拟即可

#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}

inline void solve() {
    LL n, k; cin >> n >> k;
    LL now = 1, ans = 0, tag = 1;
    while (now < n) {
        ans ++;
        now += tag;
        tag <<= 1ll;
        if (tag > k) {
            ans += (n - now + k - 1) / k;
            break;
        }
    }
    cout << ans << endl;
}
int main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto now = clock();
#endif
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(2);
    int T; cin >> T;
    while (T -- )
        solve();
#ifdef DEBUG
    cout << "============================" << endl;
    cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
    return 0;
}

C. Banknotes

贪心即可

容易看出,比能拼的数多出 \(1\) 即可。

#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}

inline void solve() {
    LL n, k; cin >> n >> k;
    vector<LL> a(n + 1);
    for (int i = 1; i <= n; i ++ ) {
        cin >> a[i];
        a[i] = (LL)pow(10, a[i]);
    }
    k ++;
    LL res = 0;
    for (int i = 1; i < n; i ++ ) {
        LL d = a[i + 1] / a[i] - 1;
        if (k >= d) {
            res += a[i] * d;
            k -= d;
        } else {
            res += a[i] * k;
            k = 0;
        }
    }
    if (!k) cout << res << endl;
    else {
        res += a[n] * k;
        cout << res << endl;
    }
}
int main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto now = clock();
#endif
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(2);
    int T; cin >> T;
    while (T -- )
        solve();
#ifdef DEBUG
    cout << "============================" << endl;
    cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
    return 0;
}

D. Red-Blue Matrix

这题的感觉就是不难,但是代码比较难理,所以以理代码逻辑为主

先说题意,就是给你一个 \(n * m\) 的数字矩阵,然后要求你给每行染成蓝色或者红色。然后再将这个矩阵分为左右两部分,

要求满足以下两点

1、左矩阵中,所有红色格的数字的最小值大于蓝色格子的最大值

2、右矩阵中,所有蓝色格的数字的最小值大于红色格子的最大值

若存在这么一种染色和分割方法,输出具体方案,否则输出不存在。

我们可以先只对左矩阵进行判断,在左矩阵满足的情况下验证右矩阵即可。

那么先解决左矩阵的子问题,贪心来看,一定是红色格的最小值越大越好。不妨我们这样设置,根据每行的最小值的前缀进行从上到下的从小到大的排序,那么就变成了判断左下矩阵的最小值大于左上矩阵的最大值,右上矩阵的最小值大于右下矩阵的最大值。

枚举切割线,然后加亿点预处理就行了,具体看代码

#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}

inline void solve() {
    int n, m; cin >> n >> m;
    vector<vector<int>> g(n + 1, vector<int> (m + 1));
    for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= m; j ++ ) cin >> g[i][j];
    vector<vector<int>> pre_max(n + 1, vector<int> (m + 2, 0));//前缀最大值
    vector<vector<int>> pre_min(n + 1, vector<int> (m + 2, INF));//前缀最小值
    vector<vector<int>> sur_max(n + 1, vector<int> (m + 2, 0));//后缀最大值
    vector<vector<int>> sur_min(n + 1, vector<int> (m + 2, INF));//后缀最小值
    //预处理前缀后缀最大最小值
    for (int i = 1; i <= n; i ++ ) {
        for (int j = 1; j <= m; j ++ ) {
            pre_max[i][j] = max(pre_max[i][j - 1], g[i][j]);
            pre_min[i][j] = min(pre_min[i][j - 1], g[i][j]);
        }
        for (int j = m; j; j -- ) {
            sur_max[i][j] = max(sur_max[i][j + 1], g[i][j]);
            sur_min[i][j] = min(sur_min[i][j + 1], g[i][j]);
        }
    }
    for (int j = 1; j < m; j ++ ) {//枚举切割线
        vector<PII> Num(n + 1);
        for (int i = 1; i <= n; i ++ ) Num[i] = {pre_min[i][j], i};//根据左矩阵的前缀最小值排序
        sort(Num.begin() + 1, Num.end());
        vector<int> up_r(n + 1, INF), down_r(n + 2);//右上是最小值,右下是最大值
        vector<int> up_l(n + 1), down_l(n + 2, INF);//左下是最小值,左上是最大值
        //预处理上面的四个数组
        for (int i = 1; i <= n; i ++ ) {
            int row = Num[i].second;
            up_l[i] = max(up_l[i - 1], pre_max[row][j]);
            up_r[i] = min(up_r[i - 1], sur_min[row][j + 1]);
        }
        for (int i = n; i; i -- ) {
            int row = Num[i].second;
            down_l[i] = min(down_l[i + 1], pre_min[row][j]);
            down_r[i] = max(down_r[i + 1], sur_max[row][j + 1]);
        }
        for (int i = n; i > 1; i -- ) {
            //枚举取的红色行数,排序后的第i到第n行都是红色
            if (down_l[i] > up_l[i - 1] && up_r[i - 1] > down_r[i]) {//如果满足就是符合题意
                cout << "YES" << endl;
                vector<char> res(n + 1, 'B');
                for (int k = n; k >= i; k -- ) res[Num[k].second] = 'R';
                for (int k = 1; k <= n; k ++ ) cout << res[k];
                cout << ' ' << j << endl;
                return ;
            }
        }
    }
    //否则就是不满足
    cout << "NO" << endl;
}
int main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto now = clock();
#endif
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(2);
    int T; cin >> T;
    while (T -- )
        solve();
#ifdef DEBUG
    cout << "============================" << endl;
    cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
    return 0;
}

E. Arena

考虑dp

状态设计 \(dp[i][j]\) 表示有 \(i\) 个人,血量范围是 \(j\) 的方案数

首先考虑最简单的,当每个人第一轮被淘汰的情况,容易看出只能在 \(1到n - 1\) 取值,对于 \(n\) 个人,每人有 \(n - 1\) 种取法,同时考虑到其血量范围,故取 \(dp[n][x] = min(n - 1, x) ^ {n}\)

如果 \(x < n - 1\) 那么只可能是第一轮就被淘汰完,否则继续考虑

考虑每轮的淘汰人数,由于不能存在最后胜利者,所以我们取每轮淘汰的人数为 \(k\)\(k \in [0, n - 2]\)

然后直接转移即可

\(dp[n][x] = \sum_{k=0}^{n - 2}(n - 1)^k * dp[n - k][x - n + 1] * C_n^i\)

稍微解释一下,由于本轮淘汰了 \(k\) 人,并且本轮所有人扣的血量为 \(n - 1\),所以我们只能从 \(dp[n - k][x - n + 1]\) 中转移,相当于 \(k\) 个人可以分配到 \(1到n - 1\) 的血量,所以是 \((n - 1)^k\),在算上从 \(n\) 个人中选择 \(i\) 个人淘汰 \(C_n^i\),得到转移式。

用记忆化搜索写即可

#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 550;
const int MOD = 998244353;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}

LL dp[N][N], c[N][N];

LL q_pow(LL a, LL b) {
    LL res = 1;
    for (; b; b >>= 1) {
        if (b & 1) res = res * a % MOD;
        a = a * a % MOD;
    }
    return res;
}

LL dfs(int n, int x) {
    if (dp[n][x]) return dp[n][x];
    dp[n][x] = q_pow(min(x, n - 1), n);
    if (x <= n - 1) return dp[n][x];
    for (int i = 0; i <= n - 2; i ++ ) dp[n][x] = (dp[n][x] + q_pow(n - 1, i) * dfs(n - i, x - n + 1) % MOD * c[n][i] % MOD) % MOD;
    return dp[n][x];
}

inline void solve() {
    int n, x; cin >> n >> x;
    for (int i = 0; i <= 500; i ++ ) {
        for (int j = 0; j <= i; j ++ ) {
            if (i == 0 || j == 0) c[i][j] = 1;
            else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD;
        }
    }
    cout << dfs(n, x) << endl;
}
int main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto now = clock();
#endif
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(2);
//    int T; cin >> T;
//    while (T -- )
        solve();
#ifdef DEBUG
    cout << "============================" << endl;
    cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
    return 0;
}
posted @ 2021-10-30 15:44  Time_Limit_Exceeded  阅读(91)  评论(0编辑  收藏  举报