SMU Summer 2024 Contest Round 7

A Make Equal With Mod

思路:

首先x >= 2,那么对于出现1的时候就没有办法处理,所以需要把所有数都变为1,从最大的数开始,每个数 mod 这个数减一 后得到1,只有当出现两个数的差为1时没有办法把全部树变为1

当没有出现1时,所有数都可以通过mod 自己 后得到0

void solve() {
    int n;
    cin >> n;
    vector<int> ve(n);
    bool ok1 = false;
    for (int i = 0; i < n; ++i) {
        cin >> ve[i];
        if (ve[i] == 1) ok1 = true;
    }
    if (ok1) {
        sort(ve.begin(), ve.end());
        for (int i = 1; i < ve.size(); ++i) {
            if (ve[i] - ve[i - 1] == 1) {
                cout << "NO\n";
                return ;
            }
        }
    }
    cout << "YES\n";
}

B Game on Ranges

思路:

贪心的先处理区间长度小的,枚举找到可行的数

struct E {
    int l, r, ans;
    bool operator<(const E &e)const {
        return (r - l) < (e.r - e.l);
    }
};

void solve() {
    int n;
    cin >> n;
    vector<E> ve(n);
    for (int i = 0; i < n; ++i) cin >> ve[i].l >> ve[i].r;
    sort(ve.begin(), ve.end());
    vector<int> st(n + 1), g;
    for (int i = 0; i < n; ++i) {
        for (int j = ve[i].l; j <= ve[i].r; ++j) {
            if (!st[j]) {
                ve[i].ans = j;
                st[j] = 1;
                break;
            }
        }
    }
    for (int i = 0; i < n; ++i) {
        cout << ve[i].l << ' ' << ve[i].r << ' ' << ve[i].ans << '\n';
    }
//    cout << '\n';
}

C Buy an Integer

思路:

x是顺着n的增加而增加的,可以二分来做

void solve() {
    int a, b, x;
    cin >> a >> b >> x;
    int l = 1, r = 1e9, ans = 0;
    auto check = [=] (int u) {
        int cnt = 0, y = u;
        while (y) {
            cnt ++, y /= 10;
        }
        int s = a * u + b * cnt;
        return s <= x;
    };
    while (l <= r) {
        int mid = l + r >> 1;
        if (check(mid)) l = mid + 1, ans = mid;
        else r = mid - 1;
    }
    cout << ans;

}

D String Formation

思路:

标记下当前串的翻转状态,每次插入操作,根据当前串的状态来插入

void solve() {
    string s;
    cin >> s;
    string g[2];
    int op = 0;
    int q;
    cin >> q;
    while (q --) {
        int t;
        cin >> t;
        if (t == 1) {
            op ^= 1;
        } else if (t == 2) {
            char c;
            cin >> t >> c;
            if (t == 1) {
                g[op].push_back(c);
            } else if (t == 2) {
                g[op ^ 1].push_back(c);
            }
        }
    }

    for (int i = g[op].size() - 1; i >= 0; --i) cout << g[op][i];
    if (op == 1) std::reverse(s.begin(), s.end());
    cout << s;
    cout << g[op ^ 1];
}

E Bouquet

思路:

花的种类不同,那么一共有2n - 1种选法(不能不选),由于花的数量不能为a或b,不能有n朵里选a或b朵,即C(n, a)和 C(n, b),这里n很大,且模数为质数,可以用lucas求组合数

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define PII pair<int, int>
const int N = 1e6 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;

int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};

int ksm(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1) res = res * a % Mod;
        b >>= 1;
        a = a * a % Mod;
    }
    return res;
}
int C(int a, int b, int p) {
    if (b > a) return 0;
    int res = 1;
    for (int i = 1, j = a; i <= b; ++i, --j) {
        res = (int)res * j % p;
        res = (int)res * ksm(i, p - 2) % p;
    }
    return res;
}

int lucas(int a, int b, int p) {               // 注意int参数类型
    if (a < p && b < p) return C(a, b, p);
    return (int)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;     // 递归让其到p范围内求解
}

void solve() {
    int n, a, b;
    cin >> n >> a >> b;
    int ans = (ksm(2, n) - 1 + Mod ) % Mod;
//    cout << ans << '\n';
    ans = ((ans - C(n, a, Mod) + Mod) % Mod - C(n, b, Mod) + Mod) % Mod;
    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 Permutation

G String Cards

思路:

贪心+dp

对于两个串a、b,通过比较a + b 和 b + a可以知道a和b的先后顺序

在考虑dp求后i个串中选j个的最小串

 这里有个误区,求的是i个串中选j个的最小串(而不是i个)

为什么呢,求一个字典序最小的串,应该是从第一个字符开始找最小的,所以应该枚举的是第一个串放与不放,则为倒着枚举第一个串放与不放,如果为正着枚举就是考虑的最后一个串放与不放

bool cmp(string a, string b) {
    return a + b < b + a;
}

void solve() {
    int n, k;
    cin >> n >> k;
    vector<string> ve(n + 1);
    for (int i = 1; i <= n; ++i) cin >> ve[i];
    sort(ve.begin() + 1, ve.end(), cmp);

    vector<vector<string> > f(n + 5, vector<string> (k + 5, "~"));
    for (int i = 1; i <= n + 1; ++i) f[i][0] = "";
    for (int i = n; i >= 1; --i) {
        for (int j = 1; j <= k && j <= n - i + 1; ++j) {
            f[i][j] = min(f[i + 1][j], ve[i] + f[i + 1][j - 1]);
        }
    }
    cout << f[1][k];
}

 

posted @ 2024-07-26 13:20  bible_w  阅读(12)  评论(0)    收藏  举报