2024牛客暑假多校第四场补题

B

每个堆的石子最多操作a[i]-1次

#include <iostream>
#include <fstream>
#include <unordered_map>
#include <vector>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <algorithm>
#include <iomanip>
using namespace std;
int main()
{
    std::ios_base::sync_with_stdio(false);

    long long n;

    cin >> n;
    vector<long long> nums(n);
    long long ans = 0;
    for (int i = 0; i < n; i++)
    {
        cin >> nums[i];
        ans += nums[i] - 1;
    }
    if (ans % 2 == 0)
        cout << "sweet" << endl;
    else
        cout << "gui" << endl;

    return 0;
}

C

模拟

#include <iostream>
#include <fstream>
#include <unordered_map>
#include <vector>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <algorithm>
#include <iomanip>
using namespace std;

struct options
{
    int op, z;
};

void printMatrix(const vector<vector<char>> &matrix)
{
    for (const auto &row : matrix)
    {
        for (char c : row)
        {
            cout << c << ' ';
        }
        cout << endl;
    }
    cout << endl; // 空一行,方便观察
}

void rotateRow(vector<vector<char>> &matrix, int row)
{
    char temp = matrix[row].back();
    for (int i = matrix[row].size() - 1; i > 0; i--)
    {
        matrix[row][i] = matrix[row][i - 1];
    }
    matrix[row][0] = temp;
    // printMatrix(matrix); // 打印旋转后的矩阵
}

void rotateCol(vector<vector<char>> &matrix, int col)
{
    char temp = matrix.back()[col];
    for (int i = matrix.size() - 1; i > 0; i--)
    {
        matrix[i][col] = matrix[i - 1][col];
    }
    matrix[0][col] = temp;
    // printMatrix(matrix); // 打印旋转后的矩阵
}

int main()
{
    std::ios_base::sync_with_stdio(false);
    int n, m, x, y, p, q;
    cin >> n >> m >> x >> y;
    x--;
    y--; // 将索引转换为0-based
    vector<vector<char>> matrix(n, vector<char>(m));
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            cin >> matrix[i][j];
        }
    }
    cin >> p >> q;
    vector<options> opts(p);

    for (int i = 0; i < q; i++)
    {
        int op, z;
        cin >> op >> z;
        z--; // 将索引转换为0-based
        opts[i] = {op, z};
    }

    for (int jk = 0; jk < p; jk++)
    {
        for (int i = 0; i < q; i++)
        {
            int op, z;
            op = opts[i].op;
            z = opts[i].z;
            if (op == 1)
            {
                rotateRow(matrix, z);
            }
            else if (op == 2)
            {
                rotateCol(matrix, z);
            }
        }
    }

    cout << matrix[x][y] << endl;
    return 0;
}

D

将这题看成看成一些积木块的堆积,进行的操作就是可以将任意一个积木块移动到任意的位置,也就是说,一共有sum个积木块的话,这个操作保证可以摆出所有的排列方式。

要求所有元素的最大公因数,设其为x,那么x一定也是sum的因数,那么sum的所有因数都可能被排列出来成为最小的那堆,或者是其更小的组成部分,那么只要满足x<=sum/n就是一个符合题意的方案,因此只需要对sum进行因数分解,然后筛选符合x<=sum/n的因数就可以了

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<long long> get_divisors(long long n)
{
    vector<long long> res;
    for (int i = 1; i <= n / i; i++) // i<=n/i绝对不会溢出
    {
        if (n % i == 0)
        {
            res.push_back(i);
            if (i != n / i)
            {
                res.push_back(n / i);
            }
        }
    }
    sort(res.begin(), res.end());
    return res;
}

int main()
{
    int n;
    cin >> n;

    vector<int> a(n);
    long long sum = 0;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        sum += a[i];
    }
    auto yinzi = get_divisors(sum);
    long long ans = 0;
    for (int i = 0; i < yinzi.size(); i++)
    {
        if (yinzi[i] <= sum / n)
        {
            ans++;
        }
    }
    if (n == 1)
        cout << 1 << endl;
    else
        cout << ans << endl;
    return 0;
}

E

如果要分割出最多的漂亮数组,那么就应该让每个子区间直接满足sum%k0,可以通过前缀和快速的知道哪些区间符合sum%k0,然后记录每个值上一次出现的位置,就可以做状态转换了
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>

using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    long long n, k;
    cin >> n >> k;

    vector<long long> a(n + 1, 0), s(n + 1, 0), pre_index(n + 1, -1), dp(n + 1, 0);
    map<long long, int> now_last_index;

    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        s[i] = (s[i - 1] + a[i]) % k;
        now_last_index[s[i]] = -1;
    }

    for (int i = 0; i <= n; i++) // 0号位置的余数是0,虽然没有这个数,但是要让第一个满足条件的区间能够被计算进去
    {
        if (now_last_index[s[i]] != -1)
        {
            pre_index[i] = now_last_index[s[i]]; // 记录上一次这个余数出现的位置
        }
        now_last_index[s[i]] = i; // 不断更新目前这个余数最后一次出现的位置
    }

    // dp[i]表示到第i个数为止,可以拆分出的符合题意的子区间的个数
    long long max_len = 0;
    for (int i = 1; i <= n; i++)
    {
        if (pre_index[i] == -1)
        {
            dp[i] = max_len;
        }
        else
        {
            dp[i] = max(max_len, dp[pre_index[i]] + 1);
        }
        max_len = max(max_len, dp[i]);
    }
    cout << max_len << endl;

    return 0;
}
posted @   NOTHINGBUTNOTHING  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
点击右上角即可分享
微信分享提示