题解 | 2025年浙江中医药大学程序设计竞赛(同步赛)

2025年浙江中医药大学程序设计竞赛(同步赛)

难度排序

Easy:K、L、C、D、E

Mid:G、H、J、I

Hard:F、B、A

AK:M

K 签到1

出题人:你安好便天晴

人数统计题。

时间复杂度 .

#include<bits/stdc++.h>
using namespace std;
int a[1010];
void solve() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    int ans = 0, k = 0;
    for (int i = 1; i <= n; i++) {
        if (a[i] == 1) {
            k++;
            ans += k;
        } else {
            k = 0;
        }
    }
    printf("%d", ans);
}
int main() {
    solve();
    return 0;
}

L 签到2

出题人:你安好便天晴

第一次出现的人名需要注意一下,别的就是语法的问题。

使用 std::map 实现时间复杂度为 .

#include<bits/stdc++.h>
using namespace std;
map<string, int> q, ci;
map<string, int> ans;
int main() {
    int t;
    cin >> t;
    int idx = 1;
    while (t--) {
        int x;
        cin >> x;
        if (x == 1) {
            string str;
            cin >> str;
            if (q[str] + 1 == idx) {
                q[str] = idx;
                ci[str]++;
                ans[str] += ci[str];
                continue;
            }
            if (q[str] != idx && q[str] + 1 != idx) {
                q[str] = idx;
                ans[str] += 1;
                ci[str] = 1;
                continue;
            }
        }
        if (x == 2) {
            string str;
            cin >> str;
            cout << ans[str] << endl;
            continue;
        }
        if (x == 3) {
            idx++;
        }
    }
    return 0;
}

C 天际线的能量平衡

出题人:你安好便天晴

只需要第一个不变,然后每当遇到后一个不合法,便把他变合法,这样的代价和最小。

这样的贪心容易被证明是正确的,具体实现看代码。

时间复杂度 .

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, ans = 0;
    cin >> n;
    vector<int> q(n + 1);
    for (int i = 1; i <= n; ++i) {
        cin >> q[i];
    }
    for (int i = 2; i <= n; ++i) {
        if (i % 2 == 0) {
            if (q[i] <= q[i - 1]) {
                ans += q[i - 1] + 1 - q[i];
                q[i] = q[i - 1] + 1;
            }
        } else {
            if (q[i] >= q[i - 1]) {
                ans += q[i] - q[i - 1] + 1;
                q[i] = q[i - 1] - 1;
            }
        }
    }
    cout << ans;
    return 0;
}

D 赚米

出题人:你安好便天晴

典型二分答案,二分答案后 验证,但是验证的时候每一步都要判一下有没有满足,因为数量增长过快,会导致爆 long long。只要不是单调不增的序列,都会有不大于 的解。

时间复杂度 .

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int>PII;
typedef pair<pair<int, int>, int>PIII;
typedef pair<long long, long long>PLL;
long long p[1000010];
void solve() {
    int n;
    long long m;
    scanf("%d%lld", &n, &m);
    long long mx = 0, f = 1e10;
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &p[i]);
    }
    for (int i = 1; i < n; i++) {
        if (p[i + 1] > p[i]) {
            mx = 1;
            f = min(f, (m + p[i + 1] - p[i] - 1) / (p[i + 1] - p[i]) * p[i]);
        }
    }
    if (mx == 0) {
        printf("-1");
        return;
    }
    long long l = 1, r = f;
    while (l < r) {
        long long x = (l + r) / 2;
        long long y = x;
        for (int i = 1; i < n; i++) {
            if (p[i + 1] > p[i]) {
                y = (y / p[i]) * p[i + 1] + y % p[i];
            }
        }
        if (y - x >= m) {
            r = x;
        } else {
            l = x + 1;
        }
    }
    printf("%lld", l);
}
int main() {
    int T = 1;
    while (T--) {
        solve();
    }
    return 0;
}

E 传送门

出题人:你安好便天晴

简单 bfs,每次都把能到的点塞进队列即可。

时间复杂度 .

#include<bits/stdc++.h>
using namespace std;
struct node {
    int idx, step;
};
vector<int> x[100005];
queue<node> q;
int n;
int a[1000005], vis[1000005], dist[1000005];
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        x[a[i]].push_back(i);
    }
    dist[1] = 0;
    q.push({1, 0});
    while (q.size() != 0) {
        node h = q.front();
        q.pop();
        int idd = h.idx;
        int stp = h.step;
        if (vis[idd] == 1) {
            continue;
        }
        vis[idd] = 1;
        dist[idd] = stp;
        if (idd == n) {
            cout << dist[n] << endl;
            break;
        }
        if (idd + 1 <= n && vis[idd + 1] == 0) {
            q.push({idd + 1, stp + 1});
        }
        if (idd - 1 >= 1 && vis[idd - 1] == 0) {
            q.push({idd - 1, stp + 1});
        }
        for (int i = 0; i < x[a[idd]].size(); i++) {
            if (vis[x[a[idd]][i]] == 0) {
                q.push({x[a[idd]][i], stp + 1});
            }
        }
    }
    return 0;
}

G 最大区间和

出题人:你安好便天晴

,因此考虑从 的值域入手,我们发现,如果 的值一样,那么肯定是区间越长越好,所以我们记录每一种前缀和最早出现的位置 和最晚出现的位置 , 那么枚举值域,答案就是 ,取最大即可。

时间复杂度 .

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef long long LL;
int n;
int a[N];
int s[N];
int idx1[N], idx2[N];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    memset(idx1, -1, sizeof idx1);
    memset(idx2, -1, sizeof idx2);
    cin >> n;
    int cnt = 0;
    for (int i = 1; i <= n; i ++ ) {
        cin >> a[i];
        if (a[i] == -1) ++ cnt;
    }
    if (cnt == n) {
        cout << -1 << '\n';
        return 0;
    }
    s[0] = 5000;
    for (int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + a[i];
    for (int i = 0; i <= n; i ++ ) idx2[s[i]] = i;
    for (int i = n; i >= 0; i -- ) idx1[s[i]] = i;
    LL res = -1e17;
    for (int i = 0; i <= 10000; i ++ ) {
        for (int j = 0; j <= 10000; j ++ ) {
            if (idx1[i] == -1 || idx2[j] == -1) continue;
            if (idx1[i] > idx2[j]) continue;
            res = max(res, (LL)(j - i) * (idx2[j] - idx1[i]));
        }
    }
    cout << res << '\n';
    return 0;
}

H elo

出题人:你安好便天晴

定义 表示选手 晋级到第 轮的概率。初始状态 (所有选手默认晋级第 轮)。

对于第 轮比赛:

  1. 分组结构:将选手划分为大小为 的组,每组分为左半区(前 人)和右半区(后 人)。
  2. 对手来源:左半区选手的对手来自右半区,反之亦然。
  3. 转移方程

直接暴力转移的复杂度是 ,无法通过本题,考虑值域优化。

1. 分组合并统计

  • 对每个半区统计各实力值的总概率,避免逐个枚举对手。
  • 例如:左半区中实力为 的选手总概率为:

2. 公式变形

将转移方程改写为:

其中 是对手半区中实力值为 的选手的总概率。

时间复杂度 .

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define ull unsigned long long
using PII = pair<int, int>;
using ld = long double;
using lll = __int128;
const int N = 1e5 + 5, M = 998244353;
ll ksm(ll a, ll b = M - 2) {
    ll res = 1;
    while (b) {
        if (b & 1)res = res * a % M;
        a = a * a % M;
        b >>= 1;
    }
    return res;
}
ll a[N][101], inv[202];
void solve() {
    int n;
    cin >> n;
    int m = 1 << n;
    ll a0;
    cin >> a0;
    for (int i = 1; i < m; i++) {
        int x;
        cin >> x;
        a[i][x] = 1;
    }
    ll ans = 1;
    for (int i = 1; i <= 200; i++)inv[i] = ksm(i);
    while (m > 1) {
        ll res = 0;
        for (int i = 1; i <= 100; i++) {
            res = (res + a0 * inv[a0 + i] % M * a[1][i]) % M;
        }
        ans = ans * res % M;
        for (int i = 2; i < m; i += 2) {
            for (int j = 1; j <= 100; j++)a[i / 2][j] = 0;
            for (int j = 1; j <= 100; j++) {
                if (!a[i][j])continue;
                for (int k = 1; k <= 100; k++) {
                    ll tmp = inv[j + k] * a[i][j] % M * a[i + 1][k] % M;
                    a[i / 2][j] = (a[i / 2][j] + j * tmp) % M;
                    a[i / 2][k] = (a[i / 2][k] + k * tmp) % M;
                }
            }
        }
        m >>= 1;
    }
    cout << ans << endl;
}
int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    int tt = 1;
    while (tt--)solve();
    return 0;
}

J 并查集

出题人:ygy0

赛前预测一下,应该会有很多人使用线段树合并,至少验题的时候是这样的。

实际上我们只需要维护每个点 能否走到

在启发式合并的时候,如果小集合里面的点 左边就是大集合,那么 连向 ,右边同理。

查询的时候找找 的老大是否越过 即可。

时间复杂度 .

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
vector<int>v[maxn];
int fa[maxn], nxt[maxn];
int find(int x) {
    return nxt[x] == x ? x : nxt[x] = find(nxt[x]);
}
void solve() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) v[i].push_back(i), fa[i] = nxt[i] = i;
    while (m--) {
        int op, l, r;
        cin >> op >> l >> r;
        if (op == 1) {
            int f1 = fa[l], f2 = fa[r];
            if (f1 == f2) continue;
            if (v[f1].size() < v[f2].size()) swap(f1, f2);
            for (auto x : v[f2]) {
                if (fa[x - 1] == f1) nxt[x - 1] = x;
                if (fa[x + 1] == f1) nxt[x] = x + 1;
                v[f1].push_back(x);
                fa[x] = f1;
            }
        } else {
            if (find(l) >= r) cout << "YES\n";
            else cout << "NO\n";
        }
    }
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

I 队列重组

出题人:你安好便天晴

个位置只能 的人去,第 个位置只能 的人去,,想明白这一点就很简单了,从后面的位置开始往前填,假设当前要填第 个位置,那么从 的人中选择初始位置最靠右的过去,使用 std::<set> 记录所有 的人初始位置,每次删去最大的即可。

最终可以得到每个人要去的位置,类比计算冒泡排序的交换次数,使用树状数组计算逆序对个数即可得到答案。

时间复杂度 .

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
#define __cs() int T; cin >> T; while (T--)
int n, x, p[maxn];
vector<int>v[maxn];
set<int>s;
struct BIT {
    int n, res, c[maxn];
    void init(int n) {
        this->n = n;
        for (int i = 1; i <= n; ++i) c[i] = 0;
    }
    void add(int x, int k = 1) {
        for (; x <= n; x += x & -x) c[x] += k;
    }
    int sum(int x) {
        for (res = 0; x; x ^= x & -x) res += c[x];
        return res;
    }
} bit;
void solve() {
    cin >> n;
    bit.init(n);
    s.clear();
    for (int i = 1; i <= n; ++i) {
        cin >> x;
        p[x] = i;
        v[i].clear();
    }
    for (int i = 1; i <= n; ++i) {
        cin >> x;
        v[x].push_back(p[i]);
    }
    ll ans = 0;
    for (int i = n; i >= 1; --i) {
        for (auto it : v[i]) s.insert(it);
        if (s.empty()) {
            cout << -1 << '\n';
            return;
        }
        x = *--s.end();
        s.erase(x);
        ans += bit.sum(x);
        bit.add(x);
    }
    cout << ans << '\n';
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    __cs()solve();
    return 0;
}

F 数星星

出题人:ygy0

本题由广州大学校赛改编而来,沿用了原题的名字。

首先对于一颗子树,最小值、最大值、节点个数是容易维护的,然后我们就会有一个期望的公差。

于是,不难想到还需要维护最大公约数。

做完了吗?我们来看下面这个例子:

此时我们期望的公差是 ,最大公约数也是 ,但显然这不是一个等差数列。

不难发现我们唯一需要做的就是判断子树内有没有重复元素(全都一样除外)。

这部分的处理可以 完成。

在 dfs 的过程中,我们同时维护以下三个值:

:节点 dfs 序编号。

:上一个颜色为 的节点的 dfn

:所有 最大值。

注意,这里的更新顺序为

在遍历完一棵以 为根的子树之后,如果 ,说明子树内存在重复元素。

本题也可以把树拍成序列再离线处理,处理方法一致。

需要注意的是,离线需要预处理区间 ,而 ST 表预处理区间 的时间复杂度为 ,可以通过本题。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
vector<int>e[maxn];
int c[maxn];
int dfn[maxn], cnt;
int g[maxn], mx[maxn], mi[maxn];
int last[maxn];
int Max, ans;
void dfs(int u) {
    dfn[u] = ++cnt;
    mx[u] = mi[u] = c[u];
    Max = max(Max, last[c[u]]);
    last[c[u]] = cnt;
    for (auto v : e[u]) {
        dfs(v);
        mx[u] = max(mx[u], mx[v]);
        mi[u] = min(mi[u], mi[v]);
        g[u] = __gcd(g[u], abs(c[u] - c[v]));
        g[u] = __gcd(g[u], g[v]);
    }
    if (mi[u] == mx[u]) {
        ans++;
        return;
    }
    if (Max < dfn[u]) {
        if (dfn[u] == cnt) {
            ans++;
            return;
        }
        if ((mx[u] - mi[u]) % (cnt - dfn[u])) return;
        int gap = (mx[u] - mi[u]) / (cnt - dfn[u]);
        if (gap == g[u]) ans++;
    }
}
void solve() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) e[i].clear(), g[i] = last[i] = 0;
    cnt = Max = ans = 0;
    for (int i = 1; i <= n; i++) cin >> c[i];
    for (int i = 2; i <= n; i++) {
        int f;
        cin >> f;
        e[f].push_back(i);
    }
    dfs(1);
    cout << ans << '\n';
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    cin >> t;
    while (t--) solve();
    return 0;
}

B 染色之旅

出题人:ygy0

首先这是一个 基环内向森林

我们考虑去倒着染色,每个点就至多被染一次,遇到染过的直接用并查集跳过就好了。

按照基环树的常规解法,我们先去找环,再将环上的点和其它点分开处理。

这样写代码量较大,比较考验实现的细节,一不小心可能罚时爆炸。

实际上我们可以使用带权并查集,也就是对每个点再维护一个到老大的距离。

这样在遍历的时候剩余步数 是很好控制的。

在对每一个未染色的点染色时,将该点 连向 ,同时更新到老大的距离就可以了。

这样我们就完全不需要管这张图的结构,代码也会比较简单。

时间复杂度 .

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
struct DSU {
    vector<int>fa, dis;
    DSU(int n) {
        fa.assign(n, 0);
        dis.assign(n, 0);
        iota(fa.begin(), fa.end(), 0);
    }
    int find(int u) {
        if (fa[u] == u) return u;
        int f = find(fa[u]);
        dis[u] += dis[fa[u]];
        return fa[u] = f;
    }
    void merge(int u, int v) {
        int f = find(u);
        dis[v] = dis[u] + 1;
        fa[v] = f;
    }
    int dist(int u) {
        find(u);
        return dis[u];
    }
};
struct {
    int u, k, c;
} q[maxn];
int nxt[maxn], col[maxn];
void solve() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) col[i] = 0;
    for (int i = 1; i <= n; i++) cin >> nxt[i];
    for (int i = 1; i <= m; i++) {
        int u, k, c;
        cin >> u >> k >> c;
        q[i] = {u, k, c};
    }
    DSU dsu(n + 1);
    for (int i = m; i >= 1; i--) {
        auto [u, k, c] = q[i];
        k -= dsu.dist(u);
        u = dsu.find(u);
        while (k >= 0 && col[u] == 0) {
            col[u] = c;
            dsu.merge(nxt[u], u);
            k -= dsu.dist(u);
            u = dsu.find(u);
        }
    }
    for (int i = 1; i <= n; i++) cout << col[i] << " ";
    cout << '\n';
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    cin >> t;
    while (t--) solve();
    return 0;
}

给一个本人验题时给出的一个码量很小的递归做法:

依然是倒着暴力修改, 表示下一次修改到点 时直接跳到点 记录从 跳了几步,利用 dfs 的特性在本次修改完成回溯时修改 ,返回 -1 表示环上的点已经全部修改完成直接退出,需要注意实现的细节。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
int t, n, q, nxt[maxn], cnt[maxn], col[maxn], y, u[maxn], k[maxn], c[maxn];
pair<int, int> dfs(int s, int p, int stp, int now, int c, bool fg) {
    if ((p == s && fg) || nxt[p] == -1) return { -1, -1 };
    if (now > stp) return { p, now };
    if (!col[p]) col[p] = c;
    pair<int, int> ans = dfs(s, nxt[p], stp, now + cnt[p], c, 1);
    return { nxt[p] = ans.first, (cnt[p] = ans.second - now) + now };
}
//s表示起点,p表示当前修改的点,stp表示要跳的总步数,now表示现在已经跳了多少步
//c表示修改的颜色,fg表示是否再一次回到了起点(用于判环)
void solve() {
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; ++i) scanf("%d", &y), nxt[i] = y, cnt[i] = 1, col[i] = 0;
    for (int i = 1; i <= q; ++i) scanf("%d%d%d", &u[i], &k[i], &c[i]);
    for (int i = q; i >= 1; --i) dfs(u[i], u[i], k[i], 0, c[i], 0);
    for (int i = 1; i <= n; ++i) printf("%d%c", col[i], " \n"[i == n]);
}
int main() {
    scanf("%d", &t);
    while (t--) solve();
    return 0;
}

A 元素使者的试炼

出题人:ygy0

非负的肯定全选上。

如果选择 ,那么第 行和第 列就可以不选了。

如果某行或某列全是负的,那我们需要在这些行列上选至少一个负的。

怎么选这些负的呢?

考虑反悔贪心。

如果对于行列分别来看,那我们一定是选第 行 / 第 列上的最大值。

不妨先选上。

如果第 行和第 列上都需要选一个呢?

这时候选 的价值 行最大值 列最大值。

又因为 每一行 / 每一列 的最大值只能被干掉一次,所以选了 就不能再选

这是一个经典的二分图最大权匹配。

左部点 和右部点 的边权就是

答案就是 非负的 + 行列最大值 + 二分图最大权。

时间复杂度 .

#include<bits/stdc++.h>
using namespace std;
struct Hungarian {
    int org_n, org_m, n, inf, ans;
    vector<vector<int>>g;
    vector<int>matchx, matchy, pre;
    vector<bool>visx, visy;
    vector<int>lx, ly;
    vector<int>slack;
    queue<int>q;
    Hungarian(int _n, int _m) {
        org_n = _n, org_m = _m, n = max(_n, _m), inf = 1e9, ans = 0;
        g.assign(n, vector<int>(n, 0));
        matchx.assign(n, -1);
        matchy.assign(n, -1);
        pre.assign(n, 0);
        visx.assign(n, 0);
        visy.assign(n, 0);
        lx.assign(n, 0);
        ly.assign(n, 0);
        slack.assign(n, 0);
    }
    void addedge(int u, int v, int w) {
        g[u][v] = max(0, w);
    }
    bool check(int v) {
        visy[v] = 1;
        if (matchy[v] != -1) {
            q.push(matchy[v]);
            visx[matchy[v]] = 1;
            return 0;
        }
        while (v != -1) {
            matchy[v] = pre[v];
            swap(v, matchx[pre[v]]);
        }
        return 1;
    }
    void bfs(int i) {
        while (q.size()) q.pop();
        q.push(i);
        visx[i] = 1;
        while (1) {
            while (q.size()) {
                int u = q.front();
                q.pop();
                for (int v = 0; v < n; v++) {
                    if (visy[v] == 0) {
                        int delta = lx[u] + ly[v] - g[u][v];
                        if (slack[v] >= delta) {
                            pre[v] = u;
                            if (delta) slack[v] = delta;
                            else if (check(v)) return;
                        }
                    }
                }
            }
            int a = inf;
            for (int j = 0; j < n; j++) {
                if (visy[j] == 0) a = min(a, slack[j]);
            }
            for (int j = 0; j < n; j++) {
                if (visx[j]) lx[j] -= a;
                if (visy[j]) ly[j] += a;
                else slack[j] -= a;
            }
            for (int j = 0; j < n; j++) {
                if (visy[j] == 0 && slack[j] == 0 && check(j)) return;
            }
        }
    }
    int solve() {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                lx[i] = max(lx[i], g[i][j]);
            }
        }
        for (int i = 0; i < n; i++) {
            fill(slack.begin(), slack.end(), inf);
            fill(visx.begin(), visx.end(), 0);
            fill(visy.begin(), visy.end(), 0);
            bfs(i);
        }
        for (int i = 0; i < n; i++) {
            if (g[i][matchx[i]]) ans += g[i][matchx[i]];
            else matchx[i] = -1;
        }
        return ans;
    }
};
int c[305][305];
int h[305], l[305];
int main() {
    int n, m;
    cin >> n >> m;
    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> c[i][j];
            if (c[i][j] >= 0) {
                ans += c[i][j];
                h[i] = 1, l[j] = 1;
            }
        }
    }
    vector<int>hmx(n, -1e9);
    vector<int>row;
    for (int i = 0; i < n; i++) {
        if (h[i] == 0) {
            for (int j = 0; j < m; j++) hmx[i] = max(hmx[i], c[i][j]);
            row.push_back(i);
            ans += hmx[i];
        }
    }
    vector<int>lmx(m, -1e9);
    vector<int>col;
    for (int j = 0; j < m; j++) {
        if (l[j] == 0) {
            for (int i = 0; i < n; i++) lmx[j] = max(lmx[j], c[i][j]);
            col.push_back(j);
            ans += lmx[j];
        }
    }
    int N = row.size(), M = col.size();
    Hungarian km(N, M);
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            int w = max(0, c[row[i]][col[j]] - hmx[row[i]] - lmx[col[j]]);
            km.addedge(i, j, w);
        }
    }
    ans += km.solve();
    cout << ans << '\n';
    return 0;
}

M.数论测试

出题人:pvzelyyds

表示 的方案数,设 的质因数分解为 的质因数分解为 的质因数分解为 ,于是对每一个质数 其指数都应该满足 ,方案数为 ,那么总方案数为 ,即 ,因此 为积性函数。

.

考虑使用 PN 筛求出 的前缀和,构造 满足 ,其中 表示 的因数个数, 表示狄利克雷卷积。则满足质数处

归纳易证 ,不想证明也可以直接暴力计算或者打表。

利用 和整除分块可以在 时间内计算 的前 项和。

时间复杂度分析:设某一 Powerful Number 被表示为 ,计算 的复杂度为 .

.

Min_25 筛可能无法通过本题。

全部评论
1 回复 分享
发布于 03-10 20:31 河南
B题简单写法的复杂度是如何保证的
点赞 回复 分享
发布于 03-10 22:34 浙江

相关推荐

05-26 10:24
门头沟学院 Java
qq乃乃好喝到咩噗茶:其实是对的,线上面试容易被人当野怪刷了
找工作时遇到的神仙HR
点赞 评论 收藏
分享
评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务