1 条题解

  • 0
    @ 2026-9-6 20:54:56

    变形怪 题解

    题意与关键信息

    • 初始体型 nnmm 种配方 x1,,xmx_1,\dots,x_m
    • 每步:若 vmodxi=0v \bmod x_i = 0,则 vv/xiv \to v / x_i;可以变形任意多次(含 00 次)。
    • 求可达的不同体型数量(含初始体型)。
    • 数据范围:1n10181 \le n \le 10^{18}1m81 \le m \le 8xi106x_i \le 10^6 且两两不同。

    从暴力到正解

    暴力搜索(n103n \le 10^3,30 分)

    DFS 枚举全部可达体型,用集合去重:

    void dfs(ll v) {
        seen.insert(v);
        for (ll xi : x) if (v % xi == 0) dfs(v / xi);
    }
    

    nn 很小时状态数有限,可直接通过。nn 一大(如 101810^{18})状态可能爆炸?——并不会爆炸,见下。

    特殊性质(xix_i 两两互质且 xinx_i \mid nxi2nx_i^2 \nmid n,10 分)

    nn 的质因数分解。因为 xix_i 两两互质且每个 xix_i 恰整除 nn 一次(xi2nx_i^2 \nmid n),每个配方一旦使用就会把 nn 中对应的那部分因子恰好除尽一次,之后该配方永远无法再用(vv 不再含 xix_i 的任何因子)。

    于是每种配方只有"用 / 不用"两种选择,且互不干扰,答案恰为:

    2m.2^{m}.

    正解:BFS 去重

    vv 能变到 v/xiv/x_i 当且仅当 xivx_i \mid v。因为每一步都保持"整除",所有可达体型都是 nn 的约数n1018n \le 10^{18} 时约数个数最多约 10510^5 个,因此 BFS 状态数有限且很小:

    unordered_set<ll> seen; queue<ll> q;
    seen.insert(n); q.push(n);
    while (!q.empty()) {
        ll v = q.front(); q.pop();
        for (ll xi : x)
            if (v % xi == 0 && seen.insert(v / xi).second)
                q.push(v / xi);
    }
    cout << seen.size();
    

    复杂度

    • 每个状态做 mm 次取模/除法,O(1)O(1) 哈希判重。
    • 状态数 \le nn 的约数个数 105\le 10^5,故 O(md(n))O(m \cdot d(n)),空间 O(d(n))O(d(n))

    易错点

    1. long longnn 可达 101810^{18},必须用 64 位整数。
    2. v=1v = 1 时不可再变1modxi=101 \bmod x_i = 1 \ne 0,BFS 不会从 11 继续扩展,天然终止。
    3. 答案包含初始体型nn 本身也要计数(入队前先 insert(n))。
    4. 配方可能永远用不上xinx_i \nmid n 时该配方无效(例如 nn 是质数时答案恒为 11),BFS 自然处理,无需特判。

    参考代码

    summercspj262B.cpp

    • 1

    信息

    ID
    255
    时间
    1000ms
    内存
    256MiB
    难度
    3
    标签
    递交数
    56
    已通过
    12
    上传者