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;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/14418897.html