[CF839D] Winter is here

Description

给定一个数列 \(a_{i}\),若子序列长度为 \(k\),最大公约数为 \(\gcd\),定义子序列的权值为 \(k \times \gcd\)。求所有 \(\gcd > 1\) 子序列的权值和,答案对 \(10^{9}+7\) 取模。

Solution

枚举 gcd 求贡献

\(cnt[i]\) 为 i 出现的次数,\(f[i]\) 为 gcd 为 i 的子序列总长

枚举 i,容斥,先算出 i|gcd 的序列的总长度,然后枚举 i 的每个倍数 j,减去 \(f[j]\),这就要求我们逆序枚举 i

考虑怎么“算出 i|gcd 的序列的总长度”,显然这玩意之和 i|x 的 x 个数有关,为 \(\frac 1 2 c 2^c = c 2^{c-1}\)

证明可用组合推导或平均思想

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1e6 + 5;
const int mod = 1e9 + 7;

int pw2[N];

void presolve_pw2()
{
    pw2[0] = 1;
    for (int i = 1; i < N; i++)
        pw2[i] = pw2[i - 1] * 2 % mod;
}

int n, a[N], f[N];
;

signed main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        a[x]++;
    }

    presolve_pw2();
    int ans = 0;

    for (int i = N - 1; i > 1; i--)
    {
        int cnt = 0;
        for (int j = i; j < N; j += i)
            cnt += a[j];
        if (cnt)
        {
            f[i] = pw2[cnt - 1] * cnt % mod;
            for (int j = i + i; j < N; j += i)
                f[i] = (f[i] - f[j] + mod) % mod;
            ans = (ans + f[i] * i) % mod;
        }
    }
    cout << ans;
}

相关文章: