牛客周赛 Round 55 ABCDE

A题:小红的字符串

题意

给定一个长度为3的字符串,小红每次可以修改其中一个字符为任意,问使得三个字符相同的最少操作次数

思路

大水题

变的越少越好,我们只需统计字符数量,取变的最少的即可

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    vector<int> a(26);
    string s; cin >> s;
    int ans = 3;
    for (int i = 0; i < 3; i ++ ) {
        a[s[i] - 'a'] += 1;
        ans = min(ans, 3 - a[s[i] - 'a']);
    }
    cout << ans << endl;
    return 0;
}

B题:小红的序列乘积

题意

定义fi为前i相的乘积,问i从1到n,有几个fi的个位数为6

思路

最后乘积的个位数只与每次相乘两数的个位数有关

所以我们只需看每个数的个位数即可

当乘起来为6时,答案加加即可 

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n; cin >> n;
    int cur = 1, ans = 0;
    for (int i = 0; i < n; i ++ ) {
        string s; cin >> s;
        int now = s.back() - '0';
        cur = now * cur % 10;
        if (cur == 6) ans += 1;
    }
    cout << ans << endl;
    return 0;
}

C题:小红的数组重排

题意

给定一个长度为n的数组a,要求你进行重新排序,满足题目要求

思路

对于相邻两项我们可以进行消去,发现要求构造的数组奇数项和偶数项都要求单增。所以我们要避免一个数出现3次的情况,因为出现3次,肯定有两个在奇数项或者偶数项,单增不了。

但是,特别地,我们要注意0的情况,上述消去基于不是0的标准。

0的情况下,只要出现两个就满足不了题意

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n; cin >> n;
    vector<int> a(n);
    map<int, int> cnt;
    bool ok = true;
    for (int i = 0; i < n; i ++ ) {
        cin >> a[i];
        if (++ cnt[a[i]] == 3 - (a[i] == 0)) ok = false;
    }
    cout << (ok ? "YES" : "NO") << endl;
    sort(a.begin(), a.end());
    for (int i = 0; i < n; i += 2) {
        cout << a[i] << ' ';
        if (i + 1 < n) cout << a[i + 1] << ' ';
    }
    cout << endl;
    return 0;
}

D题:虫洞操纵者

题意

迷宫+遇到墙可以进行穿梭

思路

还是bfs,数据是1e3,所以我们遍历整个图是1e6,对于穿梭操作,我们直接进行暴力1e3,总的就变成1e9,不会T。况且1e9是极限情况,不可能每个点都需要遍历1e3的

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int vis[N][N], d[N][N];
int dx[] = {-1, 0, 1, 0}, dy[] = {0, -1, 0, 1};
int main() {
    int n; cin >> n;
    vector<vector<int>> a(n + 2, vector<int>(n + 2, 1));
    for (int i = 1; i <= n; i ++ ) 
        for (int j = 1; j <= n; j ++ ) {
            cin >> a[i][j];
        }
    queue<int> q;
    q.push(10001);
    vis[1][1] = 1;
    while (q.size()) {
        int x = q.front() / 10000, y = q.front() % 10000;
        q.pop();
        for (int i = 0; i < 4; i ++ ) {
            int xn = x + dx[i], yn = y + dy[i];
            if (a[xn][yn]) {
                int dir = (i + 2) % 4;
                int j = 1;
                while (!a[x + dx[dir] * j][y + dy[dir] * j]) j += 1;
                xn = x + dx[dir] * (j - 1), yn = y + dy[dir] * (j - 1);
            }   
            if (vis[xn][yn]) continue;
            vis[xn][yn] = 1, d[xn][yn] = d[x][y] + 1;
            q.push(xn * 10000 + yn);
        }
    }
    cout << (vis[n][n] ? d[n][n] : -1) << endl;
    return 0;
}

E题:小红的序列乘积2.0

题意

见题目 

思路

我们考虑每一个点对于答案的贡献

首先一定是乘起来个位数是6才能加上答案

而对于前面点的情况,我们并不知道,所以可以用一个数组来储存前面i-1个数非空子序列乘积的个位数的情况

然后我们用a[i]去对前面1~9的可能情况进行遍历,如果可以为6,那么对于后面的n-i个数,无论怎么取,都可以使得答案增加1,而后面取的情况是Cx0 + Cx1 + ... + Cxx,是2的x次

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll mod = (ll)1e9 + 7;
inline ll qmi(ll a, ll b) {
    ll res = 1;
    while (b) {
        if (b & 1) res = res * a % mod;
        b >>= 1; 
        a = a * a % mod;
    }
    return res % mod;
}
int main() {
    int n; cin >> n;
    vector<ll> a(10);
    ll ans = 0;
    a[1] = 1;
    for (int i = 1; i <= n; i ++ ) {
        vector<ll> backup = a;
        string s; cin >> s;
        int x = s.back() - '0';
        for (int j = 1; j < 10; j ++ ) {
            int cur = x * j % 10;
            backup[cur] = (backup[cur] + a[j]) % mod;
            if (cur == 6) ans = (ans + a[j] * qmi(2, n - i) % mod) % mod;
        }
        a = backup;
    }
    cout << ans << endl;
    return 0;
}

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值