1 条题解

  • 0
    @ 2026-5-17 17:23:05

    K. GCDDCG 详细题解

    问题重述

    给定长度为 NN 的数组 AA,元素值在 [1,N][1,N] 内。对于每个 i=1..Ni=1..N,定义 ways(i)ways(i) 为将 AA 中的一些卡片分成两个非空集合(两集合无交集,且允许剩余卡片不使用),使得每个集合内所有数的最大公约数(GCD)恰好等于 ii 的方案数。要求计算

    i=1Niways(i)(mod998244353)\sum_{i=1}^N i \cdot ways(i) \pmod{998244353}

    前置准备

    cnt[v]cnt[v] 表示值为 vv 的卡片数量。
    定义 mul[x]=dxcnt[d]mul[x] = \sum_{d \mid x} cnt[d],即值能被 xx 整除的卡片总数。可以用筛法 O(NlogN)O(N \log N) 计算。

    预处理莫比乌斯函数 μ(x)\mu(x)1xN1\le x\le N):

    • xx 有平方因子,μ(x)=0\mu(x)=0
    • 否则 μ(x)=(1)k\mu(x)=(-1)^k,其中 kkxx 的不同质因子个数。

    第一步:GCD恰好为 11 的集合计数

    对于任意正整数 dd,满足“集合内所有数的 GCD 是 dd 的倍数”的非空子集个数为 2mul[d]12^{mul[d]}-1
    由莫比乌斯反演,GCD 恰好11 的非空子集个数为

    S1=d=1Nμ(d)(2mul[d]1)S_1 = \sum_{d=1}^N \mu(d) \cdot (2^{mul[d]}-1)

    第二步:两个集合的 GCD 均为 11 且允许重叠

    若允许两个集合有重叠(即同一张牌可以同时属于两个集合),且两个集合均非空,则方案数为

    $$T = \sum_{x=1}^N \sum_{y=1}^N \mu(x)\mu(y)\,(2^{mul[x]}-1)(2^{mul[y]}-1) = \left(\sum_{x=1}^N \mu(x)(2^{mul[x]}-1)\right)^2 $$

    第三步:不允许重叠的修正

    现在要求两个集合不相交。设 L=lcm(x,y)L = \mathrm{lcm}(x,y)。考虑所有值同时是 xx 的倍数和 yy 的倍数的卡片(即能被 LL 整除的卡片)。这些卡片不能同时出现在两个集合中,但可以任意分配给集合 11、集合 22 或都不选。对于其他卡片(是 xx 的倍数但不是 LL 的倍数,或是 yy 的倍数但不是 LL 的倍数),它们只能出现在对应的集合中(若出现在另一集合则违反 GCD 条件)。因此,计数方法如下:

    • 能被 LL 整除的卡片:每张有 33 种选择(去集合 11、去集合 22、都不去),贡献 3mul[L]3^{mul[L]}
    • 只能被 xx 整除(不被 LL 整除)的卡片:只能选入集合 11 或都不选,每张 22 种选择,共有 mul[x]mul[L]mul[x]-mul[L] 张,贡献 2mul[x]mul[L]2^{mul[x]-mul[L]}
    • 只能被 yy 整除(不被 LL 整除)的卡片:类似,贡献 2mul[y]mul[L]2^{mul[y]-mul[L]}
    • 其余卡片(不是 xx 倍数也不是 yy 倍数):只能都不选,贡献 11

    因此,若允许集合为空,则方案数为

    3mul[L]2mul[x]+mul[y]2mul[L]3^{mul[L]} \cdot 2^{mul[x]+mul[y]-2mul[L]}

    再减去空集合的情况:

    • 集合 11 为空:方案数为 2mul[y]2^{mul[y]}(因为集合 22 只能从 yy 的倍数中选非空,但这里我们允许空集,所以实际上 2mul[y]2^{mul[y]} 包括空集,但后面会统一修正)
    • 集合 22 为空:方案数为 2mul[x]2^{mul[x]}
    • 两个都空:11

    所以两个集合均非空且 GCD 分别为 xx 的倍数和 yy 的倍数的方案数为

    $$3^{mul[L]} \cdot 2^{mul[x]+mul[y]-2mul[L]} - 2^{mul[x]} - 2^{mul[y]} + 1 $$

    注意,当 x=yx=y 时,L=xL=x,上式变为 $3^{mul[x]}\cdot2^{0} - 2^{mul[x]} - 2^{mul[x]} + 1 = 3^{mul[x]} - 2\cdot 2^{mul[x]} + 1$,正确。


    第四步:GCD 恰好为 kk 的一般情况

    我们希望对于每个 kk,计算 GCD 恰好等于 kk 的方案数。
    注意到若将所有 AA 中元素除以 kk(只考虑 kk 的倍数),则问题归约到 GCD 为 11 的情形。具体地,定义新的数组 AA' 包含所有 Ai/kA_i/k(只取 kk 整除的 AiA_i),则 AA' 中数值范围 N/k\le N/k。设 mulk[d]mul_k[d] 表示在 AA' 中能被 dd 整除的卡片数,即原数组中能被 kdk\cdot d 整除的卡片数,所以 mulk[d]=mul[kd]mul_k[d] = mul[k\cdot d]

    因此,对于固定的 kk,两个集合 GCD 均为 kk 的方案数等于在 AA' 上计算两个集合 GCD 均为 11 的方案数(使用上述公式,但需要将 mulmul 替换为 mulkmul_k,且注意 x,yx,y 的范围变为 1..N/k1..\lfloor N/k\rfloor)。

    于是,我们得到

    $$ways(k) = \sum_{x=1}^{\lfloor N/k\rfloor} \sum_{y=1}^{\lfloor N/k\rfloor} \mu(x)\mu(y) \left(3^{mul_k[L']} \cdot 2^{mul_k[x]+mul_k[y]-2mul_k[L']} - 2^{mul_k[x]} - 2^{mul_k[y]} + 1\right) $$

    其中 L=lcm(x,y)L' = \mathrm{lcm}(x,y),且 mulk[t]=mul[kt]mul_k[t] = mul[k\cdot t]

    最终答案为 k=1Nkways(k)\sum_{k=1}^N k \cdot ways(k)


    第五步:高效计算

    直接枚举 k,x,yk,x,y 会超时。注意到 ways(k)ways(k) 的形式中,x,yx,y 只通过 mul[kx],mul[ky],mul[kL]mul[kx], mul[ky], mul[kL] 出现,且 μ(x),μ(y)\mu(x),\mu(y) 非零的 x,yx,y 数量较少(无平方因子)。利用莫比乌斯函数的性质,我们可以交换求和次序。

    u=kxu=kx, v=kyv=ky,则 x=u/kx=u/k, y=v/ky=v/k 要求 kuk\mid ukvk\mid v。但这样会引入除法,不如直接枚举三元组 (G,x,y)(G, x', y') 如原题解所述。

    原题解采用另一种方法:先计算 k=1Nkways(k)\sum_{k=1}^N k \cdot ways(k) 的整体表达式,并转化为枚举三元组 (w1,w2,w3)(w_1,w_2,w_3) 其中 w3=Lw_3 = Lw1=Gw_1=Gw2/w1=xw_2/w_1=x'w3/w2=yw_3/w_2=y'。具体推导如下:

    ways(k)ways(k) 表达式代入,并利用 $\sum_{k} k \cdot 3^{mul[kL]}\cdot 2^{mul[kx]+mul[ky]-2mul[kL]}$ 等项。经过复杂的组合变换(参见原题解),最终只需枚举所有满足 LNL\le N 的三元组 (G,x,y)(G,x',y'),其中 x,yx',y' 互质,且 L=GxyL=G\cdot x'\cdot y',并贡献一个与 mul[G],mul[Gx],mul[Gy],mul[L]mul[G], mul[Gx'], mul[Gy'], mul[L] 有关的项,乘以 μ(Gx)μ(Gy)\mu(Gx')\mu(Gy') 再乘以 GG 等因子。实际实现时,枚举 w1=Gw_1=Gw2=Gxw_2=G\cdot x'w3=Gxyw_3=G\cdot x'\cdot y',且 w1w2w3Nw_1\mid w_2\mid w_3\le N,并保证 gcd(x,y)=1\gcd(x',y')=1 以及 μ(Gx)0, μ(Gy)0\mu(Gx')\neq0,\ \mu(Gy')\neq0。由于 μ\mu 非零的数很少,实际枚举量约为 2×1072\times10^7,可以接受。


    算法步骤总结

    1. 读入 NN 和数组 AA,统计 cnt[v]cnt[v]
    2. 计算 $mul[d] = \sum_{t=1}^{\lfloor N/d\rfloor} cnt[d\cdot t]$(倍数求和)。
    3. 线性筛计算 μ(1..N)\mu(1..N)
    4. 预处理 2p2^p3p3^p 对模数取幂(pp 最大为 NN)。
    5. 枚举所有三元组 (G,a,b)(G, a, b) 满足 GabNG\mid a\mid b\le N,且 gcd(a/G,b/a)=1\gcd(a/G, b/a)=1,且 μ(a)0, μ(b)0\mu(a)\neq0,\ \mu(b)\neq0
      x=a/Gx = a/Gy=b/ay = b/aL=bL = b。则贡献为:$$\mu(a)\mu(b) \cdot \left(3^{mul[L]} \cdot 2^{mul[a]+mul[b]-2mul[L]} - 2^{mul[a]} - 2^{mul[b]} + 1\right) \cdot G $$注意这里 GG 对应原式中的 kk?实际上最终累加时需要乘以 kk,而这里 kk 就是 GG?仔细看:原题解中 ways(k)ways(k) 的表达式里已经包含了 kk 的因子?不,ways(k)ways(k) 本身没有 kk,最后答案要乘以 kk。经过推导,最终累加时每个三元组贡献的系数正好是 GG。因此直接累加上述值即可。
    6. 将所有贡献求和,输出模 998244353998244353

    复杂度

    枚举三重循环:最外层 GG,中间层 aaGG 的倍数,内层 bbaa 的倍数。加上互质和莫比乌斯非零的限制,总枚举次数约为 2×1072\times10^7,可以在 1 秒内完成(常数优化后)。


    参考代码

    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    const int MOD = 998244353;
    const int MAXN = 200000;
    
    int N;
    int cnt[MAXN+5], mul[MAXN+5];
    int mu[MAXN+5];
    vector<int> primes;
    bool is_composite[MAXN+5];
    
    void sieve() {
        mu[1] = 1;
        for (int i=2; i<=N; ++i) {
            if (!is_composite[i]) {
                primes.push_back(i);
                mu[i] = -1;
            }
            for (int p : primes) {
                if (i*p > N) break;
                is_composite[i*p] = true;
                if (i % p == 0) {
                    mu[i*p] = 0;
                    break;
                } else {
                    mu[i*p] = -mu[i];
                }
            }
        }
    }
    
    ll pow2[MAXN+5], pow3[MAXN+5];
    void precompute_pow() {
        pow2[0] = pow3[0] = 1;
        for (int i=1; i<=N; ++i) {
            pow2[i] = pow2[i-1] * 2 % MOD;
            pow3[i] = pow3[i-1] * 3 % MOD;
        }
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> N;
        for (int i=1; i<=N; ++i) {
            int x;
            cin >> x;
            cnt[x]++;
        }
        // 计算 mul[d] = 能被 d 整除的数的个数
        for (int d=1; d<=N; ++d) {
            for (int t=d; t<=N; t+=d) {
                mul[d] += cnt[t];
            }
        }
        sieve();
        precompute_pow();
    
        ll ans = 0;
        // 枚举 G, a, b
        for (int G=1; G<=N; ++G) {
            // 剪枝:mu[G] 为 0 时后面的 mu[a] 也必定为 0 ?不,a 是 G 的倍数,mu[a] 可能非零
            // 但 mu[a] 非零要求 a 无平方因子,所以 a 必须是若干不同质数的乘积,且包含 G 的质因子。
            for (int a=G; a<=N; a+=G) {
                if (mu[a] == 0) continue;
                int x = a / G;
                for (int b=a; b<=N; b+=a) {
                    if (mu[b] == 0) continue;
                    int y = b / a;
                    if (__gcd(x, y) != 1) continue;
                    int L = b;
                    ll term = (pow3[mul[L]] * pow2[mul[a] + mul[b] - 2*mul[L]] % MOD
                              - pow2[mul[a]] - pow2[mul[b]] + 1) % MOD;
                    term = term * mu[a] % MOD * mu[b] % MOD;
                    ans = (ans + term * G) % MOD;
                }
            }
        }
        ans = (ans % MOD + MOD) % MOD;
        cout << ans << '\n';
        return 0;
    }
    

    注意:上述代码直接枚举可能较慢,实际实现时需进一步优化:例如预先存储所有 μ\mu 非零的数,并用整除关系建图。但根据官方题解,枚举次数约 2×1072\times10^7,在 N=2×105N=2\times10^5 时可接受。

    本题的核心是莫比乌斯反演与三重循环枚举,通过巧妙地利用 μ\mu 的非零性质,将复杂度控制在可接受范围内。

    • 1

    信息

    ID
    7173
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者