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
如果你有任何建议或者批评和补充,请留言指出,不胜感激

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值