Loading

12.19 CW 模拟赛 T2. 数

思路

赛时读错题了, 虽然说读对了不一定能做出来, 但是还是比较可惜

首先阐述一下题意, 对 \(S\) 数组进行插入和删除操作, 每次询问让你用 \(T\) 中的质数组合出 \(x\) , 然后将 \(S\) 中的数乘以 \(x\) 之后求最多的完全立方数个数

那么显然的, 我们对于每一个数, 都可以拆成质数之积, 那么显然的, 我们可以知道每个数需要什么质数才能凑成完全立方数

\(op = 1\)

如果这个数可能成为一个完全立方数, 我们记录这个数需要 \(T\) 中质数的个数, 这应该是一个 \(0, 1, 2\) 串串, 丢进去

时间复杂度 \(\mathcal{O} (M)\)

\(op = 2\)

扔出来

时间复杂度 \(\mathcal{O} (M)\)

\(op = 3\)

找最大, 结束

题解使用了 \(0, 1, 2 \ \rm{trie}\) , 但是被 \(\rm{klr}\)\(\rm{pbds}\) 轻松冲过

还是稍微写一些 \(\rm{trie}\) , 补一下我的神秘基础

实现

代码

#include <bits/stdc++.h>
const int MAXM = 520;
const int MAXN = 5e6 + 1;
typedef long long ll;

void write(__int128 x) {
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
    return;
}

int M;
int prime[MAXM];
int Q;

struct node {
    int App; // 串串的出现次数
    int son[3]; // 下一个节点
    int prime;
    __int128 x;
} Tree[MAXN];
int cnt = 1; // 0 为根节点

bool check(ll rest)
{
    ll l = 1, r = 1000000;
    while (l <= r)
    {
        ll mid = (l + r) >> 1;
        if (mid * mid * mid == rest)
            return 1;
        mid * mid * mid < rest ? l = mid + 1 : r = mid - 1;
    }
    return 0;
}

std::vector<int> mstr;
std::set<int> leave;

void ins() {
    ll num; scanf("%lld", &num);
    mstr.clear();
    for (int i = 1; i <= M; i++) {
        int cnt = 0; while (!(num % prime[i])) cnt++, num /= prime[i];
        mstr.push_back((3 - (cnt % 3)) % 3);
    }
    if (num != 1 && !check(num)) return;

    ll now = 0;
    __int128 nowx = 1;
    for (int i = 0; i < M; i++) {
        int ch = mstr[i];
        for (int j = 1; j <= ch; j++) nowx *= prime[i + 1];
        if (!Tree[now].son[ch]) Tree[now].son[ch] = cnt++;
        now = Tree[now].son[ch];
        Tree[now].prime = prime[i + 1];
        Tree[now].x = nowx;
    }
    Tree[now].App++;
    leave.insert(now);
}

void del() {
    ll num; scanf("%lld", &num);
    mstr.clear();
    for (int i = 1; i <= M; i++) {
        int cnt = 0; while (!(num % prime[i])) cnt++, num /= prime[i];
        mstr.push_back((3 - (cnt % 3)) % 3);
    }
    if (num != 1 && !check(num)) return;

    ll now = 0;
    for (int i = 0; i < M; i++) {
        int ch = mstr[i];
        now = Tree[now].son[ch];
    }
    Tree[now].App--;
}

__int128 ansx;
int ans;

void solve()
{
    while (Q--) {
        int op; scanf("%d", &op);

        if (op == 1) ins();
        if (op == 2) del();
        if (op == 3) {
            ans = 0, ansx = 0;
            for (auto i : leave) {
                int now = i;
                if (Tree[now].App == 0) {
                    continue;
                }
                __int128 x = Tree[now].x;
                if (ans == Tree[now].App) ansx = std::min(ansx, x);
                if (ans < Tree[now].App) ans = Tree[now].App, ansx = x;
            }
            write(ansx); printf("\n");
        }
    }
}

signed main()
{
    scanf("%d", &M);
    for (int i = 1; i <= M; i++)
        scanf("%d", &prime[i]);
    scanf("%d", &Q);

    solve();

    return 0;
}

总结

注意读题

字符串插入删除, 字典树是最快的

posted @ 2024-12-19 17:40  Yorg  阅读(12)  评论(0)    收藏  举报