周赛题解

admin 发布于 2025-03-13 1875 字 425 次阅读


A

根据题意模拟即可,需要注意的就是不要拿1直接除30,这样的话会产生精度问题,所以我们可以把a[1]乘以30跟总和比较。

#include<bits/stdc++.h>
#define int long long
#define ll unsigned long long
#define pii pair<int,int>
#define endl '\n'

using namespace std;

const int N = 2e6 + 5, P = 131, mod = 1e9 + 7, INF = 1e18;




void solve()
{
    vector<int> a(7);
    int ans = 0;
    for (int i = 1; i <= 6; i++) cin >> a[i], ans += a[i];
    if (a[1] * 30 < ans) cout << "Yes" << endl;
    else cout << "No" << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
    solve();

    return 0 ^ 0;
}

B

首先将所有小球求和对k取模,这样就得到最后会剩多少个球,设最后会剩下sum个球,那么我们可以贪心的先保留种类最大的,这样依次从大到小取球。

#include<bits/stdc++.h>
#define int long long
#define ll unsigned long long
#define pii pair<int,int>
#define endl '\n'

using namespace std;

const int N = 2e6 + 5, P = 131, mod = 1e9 + 7, INF = 1e18;




void solve()
{
    int n, k;
    cin >> n >> k;
    vector<int> a(n + 1);
    int sum = 0;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        sum += a[i];
    }
    sort(a.begin() + 1, a.end());
    sum %= k;   // 最后会剩下小球的数量
    int ans = 0;
    for (int i = n; i >= 1; i--) {
        if (sum >= a[i]) {
            ans++;
            sum -= a[i];
        }
        else break;
    }
    if (sum != 0) ans++;// 如果sum还有剩,那么说明这种类的小球还没拿完,所以答案也要把这种算上。
    cout << ans << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
    solve();

    return 0 ^ 0;
}

C

一个数是9的倍数那么这个数取模9的结果一定为0,我们可以直接从前往后暴力枚举切掉的位置统计答案即可。

#include<bits/stdc++.h>
#define int long long
#define ll unsigned long long
#define pii pair<int,int>
#define endl '\n'

using namespace std;

const int N = 2e6 + 5, P = 131, mod = 1e9 + 7, INF = 1e18;




void solve()
{
    string s;
    cin >> s;
    int ans = 0, sum = 0;
    for (int i = 0; i < s.size(); i++) {
        sum = sum * 10 + s[i] - '0';
        if (sum % 9 == 0) ans++;
        sum %= 9;
    }
    cout << ans << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
    solve();

    return 0 ^ 0;
}

D

暴力搜素板子题,没什么好讲的。

#include<bits/stdc++.h>
#define int long long
#define ll unsigned long long
#define pii pair<int,int>
#define endl '\n'

using namespace std;

const int N = 2e6 + 5, P = 131, mod = 1e9 + 7, INF = 1e18;



int n, m;
int a[1005][1005];
vector<pii> dd{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
int st[1005][1005];
int ans, sum;
void dfs(int x, int y)
{
    st[x][y] = 1;
    sum += a[x][y];
    for (auto [dx, dy] : dd) {
        int xx = dx + x, yy = dy + y;
        if (xx < 1 || xx > n || yy < 1 || yy > m) continue;
        if (st[xx][yy] || a[xx][yy] == 0) continue;
        dfs(xx, yy);
    }
}
void solve()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> a[i][j];
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (st[i][j] || a[i][j] == 0) continue;
            sum = 0;
            dfs(i, j);
            ans = max(ans, sum);
        }
    }
    cout << ans << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
    solve();

    return 0 ^ 0;
}

E

直接枚举把前面i(i <= n)位放到最后一位再使用花费B,使字符串变成回文串所花费的代价,取所有情况中的最小值即可,时间复杂度(O(n^2))。

#include<bits/stdc++.h>
#define int long long
#define ll unsigned long long
#define pii pair<int,int>
#define endl '\n'

using namespace std;

const int N = 2e6 + 5, P = 131, mod = 1e9 + 7, INF = 1e18;




void solve()
{
    int n, a, b;
    cin >> n >> a >> b;
    string s;
    cin >> s;
    auto check = [&] (string t) -> int{     // 娜姆达表达式,跟你把函数写在外面效果是一样的
        int cnt = 0;
        for (int i = 0, j = t.size() - 1; i < j; i++, j--) {
            if (t[i] != t[j]) cnt++;
        }
        return cnt * b;
    };
    int ans = check(s);
    for (int i = 0; i < n; i++) {
        string t;
        for (int j = i + 1; j < n; j++) t.push_back(s[j]);  
        for (int j = 0; j <= i; j++) t.push_back(s[j]); // 将前i个字符放在最后
        // check函数为对字符串t全使用第二种操作变成回文串所需要的花费。
        ans = min(ans, check(t) + a * (i + 1));  // a * (i + 1) 就是第一种操作所需要的花费。
    }
    cout << ans << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
    solve();

    return 0 ^ 0;
}

F

如果一个存在一个位置能够同时攻击到王和后,那么我从王的位置通过移动也一定能够与后的位置重合,所以我们直接可以从王的位置分别枚举八个不同的路径,看最后是否能够跟后的位置重合,需要注意的是可能会多个路径重复一个位置,所以我们可以用map标记这个位置是否来过。

#include<bits/stdc++.h>
#define int long long
#define ll unsigned long long
#define pii pair<int,int>
#define endl '\n'

using namespace std;

const int N = 2e6 + 5, P = 131, mod = 1e9 + 7, INF = 1e18;



vector<pii> d{{1, -1}, {1, 1}, {-1, 1}, {-1, -1}};
void solve()
{
    int a, b, x1, y1, x2, y2;
    cin >> a >> b >> x1 >> y1 >> x2 >> y2;
    vector<pii> dd;  // 将八个方向存在数组dd中
    for (auto [dx, dy] : d) {
        dd.push_back({a * dx, b * dy});
        dd.push_back({b * dx, a * dy});
    }
    map<pii, int> mp;
    int ans = 0;
    for (auto [dx, dy] : dd) {    // 直接从王的位置暴力枚举八个方向
        int xx = x1 + dx, yy = y1 + dy;
        bool flag = 0;
        for (auto [x, y] : dd) {
            if (x + xx == x2 && y + yy == y2) {    // 看是否能到达后的位置
                flag = 1;   
                break;
            }
        }
        if (flag) {
            if (mp[{xx, yy}] == 0) ans++;
            mp[{xx, yy}] = 1;
        }
    }
    cout << ans << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
    solve();

    return 0 ^ 0;
}

G

考了一个结构体排序,直接根据题意模拟即可, 具体看代码。

#include<bits/stdc++.h>
#define int long long
#define ll unsigned long long
#define pii pair<int,int>
#define endl '\n'

using namespace std;

const int N = 2e6 + 5, P = 131, mod = 1e9 + 7, INF = 1e18;



struct node{
    int id, cnt, t;
};
void solve()
{
    int n, m, q;
    cin >> n >> m >> q;
    vector<node> a(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> a[i].id >> a[i].cnt >> a[i].t;
    }
    auto cmp = [&] (node l, node r) -> bool {   // 排序函数
        if (l.cnt == r.cnt) return l.t < r.t;  // 如果通过的题数一样,那么罚时少的排前面。
        return l.cnt > r.cnt;  // 否则返回题数多的队伍
    };
    sort(a.begin() + 1, a.end(), cmp);   // 结构体排序,自定义排序规则cmp
    int cnt = a[m].cnt, t = a[m].t;  // 先记录第m支队伍的通过题数跟罚时,因为可能会出现成绩并列的情况。

    for (int i = 1; i <= m; i++) {
        if (a[i].id == q) {   // 暴力查找前面的m支队伍是否存在编号为q的队伍
            cout << "区域赛,启动!" << endl;
            return;
        }
    }
    for (int i = m + 1; i <= n; i++) {
        if (a[i].cnt == cnt && a[i].t == t) {   // 查找m支队伍之后是否存在符合条件的
            if (a[i].id == q) {
                cout << "区域赛,启动!" << endl;
                return;
            }
        }
        else break;
    }
    cout << "下次一定" << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
    solve();

    return 0 ^ 0;
}

最后更新于 2025-03-13