AtCoder Beginner Contest 167(补题)

Posted 佐鼬Jun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 167(补题)相关的知识,希望对你有一定的参考价值。

C - Skill Up



题意:

高桥对于 M M M种算法的基础是0,现在有N本书,每本书对这M种算法都有加成,第 i i i本书,售价 C i C_i Ci元,对于算法的提升是 A i , 1 A_{i,1} Ai,1 A i , 2 A_{i,2} Ai,2 A i , 3 A_{i,3} Ai,3 A i , M A_{i,M} Ai,M,现在要求使高桥对于M种算法的基础超过X,问最少花多少钱。

思路:

N和M的数据范围只有12,可以直接暴力dfs搜索,注意加一点剪枝,就可以,这里我写的搜索参数
dfs(int u u u, int c o s t cost cost, int s u m [ ] sum[] sum[]) 意思使,选择了第u个书,现在花费使cost, s u m [ ] sum[] sum[]代表对于M种算法,每个的基础值,搜所有情况,然后取最小值即可,不符合要求的话,就输出-1

#include <bits/stdc++.h>
using namespace std;
const int N = 15;
#define inf 0x3f3f3f3f
int a[N][N];
int n, m, x;
int c[N];
int vis[N];
int sum[N];
int res;

void dfs(int u, int cost, int sum[]) {
    if (cost >= res) {
        return;
    }
    bool flag = 1;
    for (int j = 1; j <= m; j++) {
        if (sum[j] < x) {
            flag = 0;
            break;
        }
    }
    if (flag) {
        res = cost;
        return;
    }
    for (int i = u + 1; i <= n; i++) {
        if (!vis[i]) {
            vis[i] = 1;
            for (int j = 1; j <= m; j++) {
                sum[j] += a[i][j];
            }
            dfs(i, cost + c[i], sum);
            for (int j = 1; j <= m; j++) {
                sum[j] -= a[i][j];
            }
            vis[i] = 0;
        }
    }
}
int main() {
    cin >> n >> m >> x;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &c[i]);
        for (int j = 1; j <= m; j++) {
            scanf("%d", &a[i][j]);
        }
    }
    res = inf;
    for (int i = 1; i <= n; i++) {
        int cost = c[i];
        memset(sum, 0, sizeof(sum));
        for (int j = 1; j <= m; j++) {
            sum[j] += a[i][j];
        }
        vis[i] = 1;
        dfs(i, cost, sum);
    }
    if (res == inf)
        puts("-1");
    else {
        cout << res << endl;
    }
}

D - Teleporter


题意:

现在给你 n n n个数,即n个城市, a i a_i ai代表城市 i i i可以传送 a i a_i ai号城市,高桥现在要从1号城市走,问传送 k k k次,最终传送到哪个城市

思路:

标记环路,一旦进入了环路,就会循环不停地走,找从1开始走的路径,一旦进了环路,标记出环路,把走到环路后,剩下的次数对 k k k取模,看能到哪个点。如果还没走到环,就停止了,就直接输出就行。
先找路径,发现有循环回来了,就在用一个数组来存环路
找路径,就直接从1号点,往后走就行,如果走回之前走过的点,就说明有环路了,再记录环路。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
#define ll long long
int a[N];
vector<int> path, cycle;
map<int, int> m;
ll n, k;

int main() {
    cin >> n >> k;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    for (int i = 1;; i = a[i]) {
        if (!m[a[i]]) {
            path.push_back(a[i]);
            m[a[i]] = 1;
        } else {
            bool flag = 0;
            for (int j : path) {
                if (j == a[i]) flag = 1;
                if (flag) cycle.push_back(j);
            }
            break;
        }
    }
    if (k <= path.size()) {
        cout << path[k - 1] << endl;
    } else {
        k -= path.size();
        k %= cycle.size();
        int cnt = (k - 1 + cycle.size()) % cycle.size();
        cout << cycle[cnt] << endl;
    }
}

E - Colorful Blocks


题意:

n n n个球,横着排列,有 m m m种颜色(可以不全用),最多能有 k k k对相邻的球颜色相同,问有多少种涂色方案

思路:

隔板法: n n n个球,就有 n + 1 n+1 n+1个隔板,除了最两边的隔板外,每删除一个隔板,就相当于把相邻的球弄为一种颜色,最多有 k k k个相邻,说明最多可以删除 k k k个隔板,所以就是然后同一个隔板内部的可以视为一个整体,相当于是一种颜色,第一个隔板内部有 m m m种选择,第二个有 m − 1 m-1 m1个选择,第三个也有 m − 1 m-1 m1个选择,直到最后一个。
所以推出来的公式就是:
∑ i = 0 k \\sum \\limits_{i=0} ^{k} i=0k C n − 1 i C^i_{n-1} Cn1i ⋅ · ( m − 1 ) n − 1 − i (m-1)^{n-1-i} (m1)n1i ⋅ m ·m m
在答案中取模,并且记得开long long 这个题就算结束。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5 + 10;
const ll mod = 998244353;
ll fact[N], infact[N];
ll n, m, k;
ll qmi(ll a, ll k, ll p) {
    int res = 1;
    while (k) {
        if (k & 1) res = (ll)res * a % p;
        a = (ll)a * a % p;
        k >>= 1;
    }
    return res;
}
void init() {
    fact[0] = infact[0] = 1;
    for (int i = 1; i < N; i++) {
        fact[i] = (ll)fact[i - 1] * i % mod;
        infact[i] = (ll)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
    }
}
int main() {
    init();
    cin >> n >> m >> k;
    ll res = 0;
    for (int i = 0; i <= k; i++) {
        int a = n - 1, b = i;
        res = (ll)res + m * fact[a] % mod * infact[b] % mod * infact[a - b] %mod * qmi(m - 1, n - 1 - i, mod) % mod;
        res = res % mod;
    }
    cout << res << endl;
}

To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

以上是关于AtCoder Beginner Contest 167(补题)的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242