zoukankan      html  css  js  c++  java
  • [CF839D] Winter is here

    [CF839D] Winter is here

    Description

    给定一个数列 (a_{i}),若子序列长度为 (k),最大公约数为 (gcd),定义子序列的权值为 (k imes 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;
    }
    
  • 相关阅读:
    FileAttributes枚举
    File类与FileInfo类
    System.IO.Path类
    会话状态Session
    Application共享数据
    压缩、解压缩流GZipStream
    MemoryStream类
    FileMode枚举
    FileAccess枚举
    MySQL函数
  • 原文地址:https://www.cnblogs.com/mollnn/p/14387639.html
Copyright © 2011-2022 走看看