Solution -「CF645F」Cowslip Collections

\(f(i)\) 表示大小为 \(k\)\(\gcd\)\(i\) 的方案数。\(F(i)\) 表示大小为 \(k\)\(\gcd\)\(i\) 的倍数的方案数。

不难看出:\(F(i) = \sum \limits _{i | d} f(d)\)。同时记 \(w_i\) 为数列中 \(i\) 的倍数的个数,则 \(F(i) = \dbinom {w_i} {k}\)

可以莫反对吧。

\[\begin {align} f (i) &= \sum _{i | d} F(d) \mu(\frac {d} {i}) \\ \mathrm{Ans} &= \sum _{i = 1} ^{k} i \times f(i) = \sum _{i = 1} ^{k} i \sum _{i | d}\mu (\frac {d} {i}) \times \dbinom {w_d} {k} \end {align} \]

有插入操作,不难发现每加入一个数只会让若干个 \(w_x\) 加上 \(1\)

注意到这部分的贡献,应该为 \(a \times b\),其中 \(a = \dbinom {w_x + 1} {k} - \dbinom {w_x} {k}\),而 \(b = \sum \limits _{i | x} i \times \mu ({\frac {x} {i}})\)

\(b\) 可以看出是 \(\mu\)\(\mathrm{Id}\) 的卷积,也就是 \(\varphi\) ,可以线性筛预处理。

#include <cstdio>

typedef long long LL;
int Abs (int x) { return x < 0 ? -x : x; }
int Max (int x, int y) { return x > y ? x : y; }
int Min (int x, int y) { return x < y ? x : y; }

int Read () {
    int x = 0, k = 1;
    char s = getchar ();
    while (s < '0' || s > '9') {
        if (s == '-')
            k = -1;
        s = getchar ();
    }
    while ('0' <= s && s <= '9') 
        x = (x << 3) + (x << 1) + (s ^ 48), s = getchar ();
    return x * k;
}

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

void Print (int x, char s) { Write (x), putchar (s); }

const int Mod = 1e9 + 7;
const int Maxn = 1e6 + 5;

bool Flag[Maxn];
int Num[Maxn], Inv[Maxn], Fac[Maxn], Phi[Maxn], Cnt[Maxn], Len = 0;

int C (int n, int m) { return n < m ? 0 : (LL)Fac[n] * Inv[n - m] % Mod * Inv[m] % Mod; }

void Init () {
    Flag[1] = true, Phi[1] = 1;
    for (int i = 2; i < Maxn; i++) {
        if (!Flag[i])
            Num[++Len] = i, Phi[i] = i - 1;
        for (int j = 1; j <= Len; j++) {
            if (i * Num[j] >= Maxn)
                break;
            Flag[i * Num[j]] = true;
            if (i % Num[j] == 0) {
                Phi[i * Num[j]] = Phi[i] * Num[j];
                break;
            }
            Phi[i * Num[j]] = Phi[i] * Phi[Num[j]];
        }
    }
    Inv[1] = 1;
    for (int i = 2; i < Maxn; i++)
        Inv[i] = (LL)(Mod - Mod / i) * Inv[Mod % i] % Mod;
    Fac[0] = 1, Inv[0] = 1;
    for (int i = 1; i < Maxn; i++) {
        Fac[i] = (LL)Fac[i - 1] * i % Mod;
        Inv[i] = (LL)Inv[i - 1] * Inv[i] % Mod;
    }
}

int main () {
    Init ();
    int n = Read (), k = Read (), q = Read (), Res = 0;
    for (int i = 1, x; i <= n; i++) {
        x = Read ();
        for (int j = 1; j * j <= x; j++) {
            if (x % j)
                continue;
            Cnt[j]++, Res = (Res + (LL)Phi[j] * (C (Cnt[j], k) - C (Cnt[j] - 1, k) + Mod) % Mod) % Mod;
            if (j * j != x)
                Cnt[x / j]++, Res = (Res + (LL)Phi[x / j] * (C (Cnt[x / j], k) - C (Cnt[x / j] - 1, k) + Mod) % Mod) % Mod;
        }
    }
    for (int i = 1, x; i <= q; i++) {
        x = Read ();
        for (int j = 1; j * j <= x; j++) {
            if (x % j)
                continue;
            Cnt[j]++, Res = (Res + (LL)Phi[j] * (C (Cnt[j], k) - C (Cnt[j] - 1, k) + Mod) % Mod) % Mod;
            if (j * j != x)
                Cnt[x / j]++, Res = (Res + (LL)Phi[x / j] * (C (Cnt[x / j], k) - C (Cnt[x / j] - 1, k) + Mod) % Mod) % Mod;
        }
        Print (Res, '\n');        
    }
    return 0;
}
posted @ 2022-07-15 14:44  STrAduts  阅读(55)  评论(1编辑  收藏  举报