zoukankan      html  css  js  c++  java
  • Codeforces839D Winter is here 容斥

    /**
    题目:Codeforces839D Winter is here
    链接:http://codeforces.com/contest/839/problem/D
    题意:给定n个数,求所有的最大公约数>1的子集的贡献之和。
    一个子集的贡献为最大公约数*子集大小
    思路:
    cnt[i]表示约数为i的数的个数。
    ans[i]表示约数为i的所有k的和。
    
    已知ans[i]可以求得贡献为i*ans[i];
    
    cnt[i]个数的长度为(sigma(k))cnt[i]*(2^(cnt[i]-1)); 即所有子集长度的和。
    但是其中有些子集的gcd不是等于i。所以要减去。
    逆序枚举,ans[i] = cnt[i]*(2^(cnt[i]-1)) - sigma(ans[j]);(j%i==0&&j/i>1)
    
    */
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <iostream>
    #include <vector>
    using namespace std;
    typedef long long LL;
    #define ms(x,y) memset(x,y,sizeof x)
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    const int maxn = 1e6 + 100;
    int cnt[maxn];
    int sum[maxn];
    LL ans[maxn];
    LL Pow(LL x, int y)
    {
        LL p = 1;
        while (y)
        {
            if (y & 1) p = p*x%mod;
            x = x*x%mod;
            y >>= 1;
        }
        return p;
    }
    int main()
    {
        int T, cas = 1;
        int n;
        while (scanf("%d",&n)==1)
        {
            int x, mas = 0;
            ms(cnt,0);
            ms(sum,0);
            ms(ans,0);
            for(int i = 1; i <= n; i++){
                scanf("%d",&x);
                mas = max(mas,x);
                sum[x]++;
            }
            for(int i = 2; i < maxn; i++){
                for(int j = i; j < maxn; j+=i){
                    cnt[i] += sum[j];
                }
            }
            LL res = 0;
            for(int i = mas; i >= 2; i--){
                if(cnt[i]==0) continue;
                LL num = 0;
                for(int j = 2*i; j <= mas; j+=i){
                    num = (num+ans[j])%mod;
                }
                ans[i] = (cnt[i]*Pow(2,cnt[i]-1)%mod-num+mod)%mod;
                res = (res+ans[i]*i%mod)%mod;
            }
            printf("%I64d
    ",res);
        }
    
        return 0;
    }
  • 相关阅读:
    用Java实现四则运算
    敏捷开发角色分配
    需求分析之WBS
    需求分析之NABCD
    电梯演说
    开发流程的选择
    软件团队模式的选择
    维护日程管理项目
    日程管理系统中找错误
    Android的测试
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7356919.html
Copyright © 2011-2022 走看看