zoukankan      html  css  js  c++  java
  • 2021牛客寒假算法基础集训营4

    2021牛客寒假算法基础集训营4

    A 九峰与签到题

    题目有歧义, 白wa4发

    int main() {
        IOS; cin >> m >> n;
        rep (i, 1, m) {
            int x; cin >> x >> op;
            if (op[0] == 'A') ++a[x];
            else ++b[x];
            if (a[x] < b[x]) c[x] = 1;
        }
        bool f = 0;
        rep (i, 1, n) if (!c[i]) cout << i << ' ', f = 1;
        if (!f) cout << -1;
        return 0;
    }
    

    B 武辰延的字符串

    kmp

    int lens, lent, f[N], extend[N];
    char s[N], t[N];
    void kmp(char* t, int lent) { //t从1开始
        int j = 0, k = 2;
        while (j + 2 <= lent && t[j + 1] == t[j + 2]) ++j;
        f[2] = j; f[1] = lent;
        for (int i = 3, p = k + f[k] - 1; i <= lent; ++i, p = k + f[k] - 1)
            if (i + f[i - k + 1] - 1 < p) f[i] = f[i - k + 1];
            else {
                j = max(0, p - i + 1);
                while (j + i <= lent && t[j + 1] == t[i + j]) ++j;
                f[i] = j; k = i;
            }
    }
    void ex_kmp(char *s, char *t, int lens, int lent) { //s, t下标都是从1开始
        int j = 0, k = 1;
        while (j + 1 <= min(lens, lent) && s[j + 1] == t[j + 1]) ++j;
        extend[1] = j;
        for (int i = 2, p = k + extend[k] - 1; i <= lens; ++i, p = k + extend[k] - 1)
            if (i + f[i - k + 1] - 1 < p) extend[i] = f[i - k + 1];
            else {
                j = max(0, p - i + 1);
                while (j + i <= lens && j + 1 <= lent && t[j + 1] == s[i + j]) ++j;
                extend[i] = j; k = i;
            }
    }
    int main() {
        IOS; cin >> t + 1 >> s + 1;
        lent = strlen(t + 1); lens = strlen(s + 1);
        kmp(t, lent); ex_kmp(s, t, lens, lent);
        ll ans = 0;
        rep (i, 1, extend[1]) ans += extend[i + 1];
        cout << ans;
        return 0;
    }
    

    E 九峰与子序列

    哈希一下, 在倒着dp就行了

    const int N = 5e6 + 5, p = 131;
     
    int n, m, _, k, cas;
    char s[N];
    ull has[N], bas[N];
    ll f[N];
     
    int main() {
        cin >> n >> (s + 1); bas[0] = f[0] = 1;
        for (k = 1; s[k]; ++k) has[k] = has[k - 1] * p + s[k], bas[k] = bas[k - 1] * p;
        for (int i = 1; i <= n; ++i) {
            cin >> s + 1; ull cur = 0;
            for (m = 1; s[m]; ++m) cur = cur * p + s[m];
            for (int j = k - m; j >= 0; --j) if (has[j] * bas[m - 1] + cur == has[j + m - 1]) f[j + m - 1] += f[j];
        }
        cout << f[k - 1];
        return 0;
    }
    

    F 魏迟燕的自走棋

    一件装备最多有两个合适的人选, 肯定是按照权值从高到低找

    用并查集表示在一个集合内的所有数可以选一次, 原先所有的人f[i] = i都可以选一次

    a[1] 可以选 x, y这两个人, 那么合并 x, y, 这两个人可以在被其他的装备选一次

    按照此思路合并贪心并查集即可

    int f[N];
    bool v[N];
    ll ans;
     
    int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
     
    int main() {
        IOS; cin >> n >> m;
        rep (i, 1, n) f[i] = i;
        rep (i, 1, m) {
            cin >> _;
            if (_ == 1) cin >> a[i].x >> a[i].w, a[i].y = a[i].x;
            else cin >> a[i].x >> a[i].y >> a[i].w;
        }
        sort(a + 1, a + 1 + m, [](node &a, node& b) { return a.w > b.w; });
        rep (i, 1, m) {
            if ((a[i].x = find(a[i].x)) != (a[i].y = find(a[i].y))) {
                if (!v[a[i].x] && !v[a[i].y]) ans += a[i].w, f[a[i].x] = a[i].y;
                else if (!v[a[i].y] || !v[a[i].x]) ans += a[i].w, v[f[a[i].x] = a[i].y] = 1;
            }
            else if (!v[a[i].x = find(a[i].x)]) ans += a[i].w, v[a[i].x] = 1;
        }
        cout << ans;
        return 0;
    }
    

    G 九峰与蛇形填数

    每次操作 x, y, z, 直接暴力记录 a[x~x+k-1][y] = {操作区间 [y, y + k - 1], 操作一开始的数 v, 每次迭代加数 -1 or 1, 这次操作是第几次}

    对于重复在 a[i][j] 上的操作, 根据区间 和 操作的顺序去覆盖当前位置或者下一个位置即可

    输出的时候每行开个map或这优先队列 记录操作按操作的优先级排序, 暴力操作输出即可 复杂度 (O(m * m + n * n * log_2m))

    struct node { int a = 1, b = 2005, f = 0, t = 0, v = 0; } p, c;
     
    int n, m, _, k, cas;
    node a[2005][2005];
     
    void add(int x, int y, node& c) {
        if (a[x][y].t == 0) { a[x][y] = c; return; }
        if (a[x][y].b <= c.b && c.t > a[x][y].t) { a[x][y] = c; return; }
        if (a[x][y].b >= c.b && c.t < a[x][y].t) return;
        else if (c.t > a[x][y].t) swap(a[x][y], c);
        c.v += (a[x][y].b + 1 - c.a) * c.f; c.a = a[x][y].b + 1; add(x, c.a, c);
    }
     
    int main() {
        IOS; cin >> n >> m;
        rep(i, 1, m) {
            int x, y, z; cin >> x >> y >> z;
            rep(j, 0, z - 1)
                if (j & 1) add(x + j, y, c = node{ y, y + z - 1, -1, i, (j + 1) * z });
                else add(x + j, y, c = node{ y, y + z - 1, 1, i, j * z + 1 });
        }
        rep(i, 1, n) {
            int c = 0; node cur = p; map<int, node> st;
            rep(j, 1, n) {
                if (a[i][j].t && a[i][j].t < cur.t) { if (a[i][j].b > cur.b) st[a[i][j].t] = a[i][j]; }
                else if (a[i][j].t) {
                    if (a[i][j].b < cur.b) st[cur.t] = cur;
                    cur = a[i][j]; c = a[i][j].v;
                }
                cout << c << ' ';
                while (j >= cur.b) {
                    auto it = st.end(); --it;
                    cur = it->second; st.erase(it);
                    c = cur.v + (j - cur.a) * cur.f;
                }
                c += cur.f;
            }
            cout << '
    ';
        }
        return 0;
    }
    

    H 吴楚月的表达式

    又不含括号, 遍历就行

    ll v[N], a[N], b[N];
    vector<pair<int, char>> h[N];
    
    ll qpow(ll a, int b) {
        ll ans = 1;
        for (; b; b >>= 1, a = a * a % mod) if (b & 1) ans = ans * a % mod;
        return ans;
    }
    
    void dfs(int x, int f, char op) {
        if (op == '+') b[x] = v[x], a[x] = (a[f] + b[x]) % mod;
        else if (op == '-') b[x] = mod - v[x], a[x] = (a[f] + b[x]) % mod;
        else if (op == '*') b[x] = b[f] * v[x] % mod, a[x] = (a[f] - b[f] + mod + b[x]) % mod;
        else if (op == '/') b[x] = b[f] * qpow(v[x], mod - 2) % mod, a[x] = (a[f] - b[f] + mod + b[x]) % mod;
        for (auto y : h[x]) dfs(y.fi, x, y.se);
    }
    
    int main() {
        IOS; cin >> n;
        rep(i, 1, n) cin >> v[i];
        rep(i, 2, n) cin >> b[i];
        rep(i, 2, n) {
            char op; cin >> op;
            h[b[i]].pb(i, op);
        }
        a[1] = b[1] = v[1]; dfs(1, 0, ' ');
        rep(i, 1, n) cout << a[i] << ' ';
        return 0;
    }
    

    J 邬澄瑶的公约数

    质因数分解

    ll qpow(ll a, int b) {
        ll ans = 1;
        for (; b; b >>= 1, a = a * a % mod) if (b & 1) ans = ans * a % mod;
        return ans;
    }
    
    void work(int n) {
        memset(b, 0, sizeof b);
        for (int i = 2; i <= n / i; ++i) 
            while (n % i == 0) ++b[i], n /= i;
        ++b[n];
    }
    
    int main() {
        IOS; cin >> n;
        rep (i, 1, n) cin >> x[i];
        rep (i ,1, n) cin >> p[i]; work(x[1]);
        rep (i, 2, 1e4) a[i] = b[i] * p[1];
        rep (i, 2, n) {
            work(x[i]);
            rep (j, 1, 10000) umin(a[j], b[j] * p[i]);
        }
        ll ans = 1;
        rep (i, 2, 10000) ans = ans * qpow(i, a[i]) % mod;
        cout << ans;
        return 0;
    }
    
  • 相关阅读:
    DbUtils类的添加,修改,删除
    QueryRunner类的八种结果处理集
    中国传统文化---------斗地主----------
    剑指Offer42 左旋字符串
    剑指Offer41 反转单词顺序,单词字符顺序不变
    剑指Offer40 和为s的连续正数序列
    剑指Offer39 数组中寻找和为sum的两个数字
    剑指Offer36 数字在排序数组中出现的次数
    剑指Offer37 二叉树深度与平衡二叉树判断
    剑指Offer38 数组所有数字出现两次,只有两个出现了一次,找出这两个数字
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/14418897.html
Copyright © 2011-2022 走看看