SMU Summer 2024 Contest Round 4

A Made Up

思路:统计A的个数,O(1)统计cnt[bc]

void solve() {
    int n;
    cin >> n;
    vector<int> cnt (n + 1), b(n + 1);
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        cnt[x] ++;
    }
    for (int i = 1; i <= n; ++i) {
        cin >> b[i];
    }
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        ans += cnt[b[x]];
    }
    cout << ans;
}

B H and V

思路:用二进制暴力枚举所选行、所选列的,然后枚举统计剩余black的个数

void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    vector<string> ve (n);
    for (int i = 0; i < n; ++i) {
        cin >> ve[i];
    }
    int ans = 0;
    for (int i = 0; i < pow(2, n); ++i) {
        for (int j = 0; j < pow(2, m); ++j) {
            int cnti = 0, cntj = 0;
            vector<vector<int> > st(n, vector<int> (m));
            for (int ii = 0; ii < n; ++ii) {
                if ((i >> ii) & 1) {
                    for (int jj = 0; jj < m; ++jj) {
                        st[ii][jj] = 1;
                    }
                }
            }
            for (int ii = 0; ii < m; ++ii) {
                if ((j >> ii) & 1) {
                    for (int jj = 0; jj < n; ++jj) {
                        st[jj][ii] = 1;
                    }
                }
            }
            for (int ii = 0; ii < n; ++ii) {
                for (int jj = 0; jj < m; ++jj) {
                    if (!st[ii][jj]) {
//                        cout << ve[ii][jj];
                        if (ve[ii][jj] == '#') cnti ++;
                        else if (ve[ii][jj] == '.') cntj ++;
                    }
//                    else cout << '_';

                }
//                cout << '\n';
            }
            if (cnti == k) {
                ans ++;
//                cout << "Y\n";
            }
        }
    }
    cout << ans;
}

C Moving Piece

思路:不管从哪个i出发,之后的路径是已定的,并且如果一直进行下去,会形成循环节,且循环长度最大为n。

那么就可以枚举从所有点出发求出可以获得的最大值,先求出循环节,若一次循环下来的贡献是正数,则可以一直进行下去,若是负数,那就在循环里找出最大值即可。

对于一次循环的贡献是正数的情况, 应该进行更多次循环,但是循环中存在负数,且不确定负数在循环中的位置,直接暴力枚举最后两次完整循环的过程中的最大答案

 

void solve() {
    int n, k;
    cin >> n >> k;
    vector<int> p(n + 1), c(n + 1);
    for (int i = 1; i <= n; ++i) cin >> p[i];
    for (int i = 1; i <= n; ++i) cin >> c[i];
    int ans = LLONG_MIN;
    for (int i = 1; i <= n; ++i) {
        vector<int> st(n + 1), sum;
        int idx = i, now = 0;
        while (!st[idx]) {
            st[idx] = 1;
            now += c[idx];
            sum.push_back(now);
            idx = p[idx];
        }
        int res = LLONG_MIN;
//        cout << "size:";
//        cout << sum.size() << '\n';
//        for (auto v:sum) cout << v << ' ';
//        cout << '\n';

        if (sum.back() <= 0) {
            for (int j = 0; j < sum.size() && j < k; ++j) {
                res = max(res, sum[j]);
            }
        } else {
            int all = 0;
            int cnt = max((k / (int)(sum.size())) - 2, 0ll);
            all += cnt * sum.back();
            if (cnt > 0) res = max(res, all);
            if (k >= sum.size()) {
                for (int j = 0; j < sum.size(); ++j) {
                    res = max(res, all + sum[j]);
                }
                all += sum.back();
            }
            if (k >= 2 * sum.size()) {
                for (int j = 0; j < sum.size(); ++j) {
                    res = max(res, all + sum[j]);
                }
                all += sum.back();
            }
            for (int j = 0; j < k % ((int)sum.size()); ++j) {
                res = max(res, all + sum[j]);
            }
        }
//        cout << i << ' ' << res << '\n';
        ans = max(ans, res);

    }
    cout << ans;
}

D Sum of Divisors

思路:类似质数筛的方法,枚举因子,这样是nlogn的

void solve() {
    int n;
    cin >> n;
    vector<int> f(n + 1, 0);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j * i <= n; ++j) {
            f[i * j] ++;
        }
    }
    int ans = 0;
    for (int i =  1; i <= n; ++i) {
        ans += i * f[i];
    }
    cout << ans;
}

E Red and Green Apples

思路:c可以转换为a或b,那就将abc全部合在一起排序,优先取最大的,保证abc选的个数和不超过x + y

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define PII pair<int, int>
const int N = 2e5 + 5, mod = 998244353;

struct E {
    int x, id;
    bool operator <(const E &e)const {
        return x < e.x;
    }
};

void solve() {
    int x, y, a, b, c;
    cin >> x >> y >> a >> b >> c;
    priority_queue<E> q;
    for (int i = 0; i < a; ++i) {
        int x;
        cin >> x;
        q.push({x, 1});
    }
    for (int i = 0; i < b; ++i) {
        int x;
        cin >> x;
        q.push({x, 2});
    }
    for (int i = 0; i < c; ++i) {
        int x;
        cin >> x;
        q.push({x, 3});
    }
    int ans = 0, z = 0;
    while ((x > 0 || y > 0) && q.size() && z < x + y) {
        auto [w, id]=q.top();
//        cout << w << '\n';
        q.pop();
        if (id == 1 && x > 0) {
            ans += w, x --;
        }
        if (id == 2 && y > 0) {
            ans += w, y --;
        }
        if (id == 3) {
            ans += w, z ++;
        }
    }
    cout << ans;
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

F Rem of Sum is Num

思路:令n = ak + b,在满足题目的条件下,n = sum[r] - sum[l - 1],b = r - l + 1,代入得到 sum[r] - sum[l - 1] = ak + r - l + 1,转换一下得到 ak = (sum[r] - r) - (sum[l - 1] - (l - 1)),且由于r - l + 1为k的余数,所以b < k,且统计sum[i] - i对k取模后的数的个数,注意只统计r - l + 1 <= k的

void solve() {
    int n, k;
    cin >> n >> k;
    vector<int> a (n + 1), sum(n + 1);
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        sum[i] = sum[i - 1] + a[i];
    }
    for (int i = 1; i <= n; ++i) {
        sum[i] -= i;
    }
    map<int, int> mp;
    mp[0] ++;
    int ans = 0;
    int l = 0;
    for (int i = 1; i <= n; ++i) {
        if (l < i - k + 1) {
            mp[sum[l++] % k] --;
        }
        int c = sum[i] % k;
//        cout << sum[i] << ' ' << c << '\n';
        ans += mp[c];
        mp[c] ++;
    }

    cout << ans;
}

G Keep Connect

思路:线性dp,f[i][j][k]表示前i列,已经删除j条边,当前上下边连通情况k(连通/不连通)

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define PII pair<int, int>
const int N = 3e3 + 5, mod = 998244353;
int f[N][N][2];

void solve() {
    int n, p;
    cin >> n >> p;
//    vector<vector<vector<int> > > f(n + 1, vector<vector<int> > (n - 1, vector<int> (2)));
    f[1][1][0] = f[1][0][1] = 1;
    for (int i = 1; i <= n; ++i) f[i][0][1] = 1;
    for (int i = 2; i <= n; ++i) {
        for (int j = 1; j <= i; ++j) {
            f[i][j][1] = (f[i - 1][j][1] + 3 * f[i - 1][j - 1][1] % p + f[i - 1][j][0]) % p;
            if (j >= 2) f[i][j][0] = (f[i][j][0] + 2 * f[i - 1][j - 2][1] % p) % p;
            f[i][j][0] = (f[i][j][0] + f[i - 1][j - 1][0]) % p;
        }
    }
    for (int i = 1; i < n; ++i) cout << f[n][i][1] << ' ';
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

 

posted @ 2024-07-16 20:17  bible_w  阅读(6)  评论(0编辑  收藏  举报