codeforce 839d.winter is here

题意:如果一个子序列的GCD为1,那么这个子序列的价值为0,否则子序列价值为子序列长度*子序列GCD

给出n个数,求这n个数所有子序列的价值和

题解:首先得想到去处理量比较少的数据的贡献,这里处理每个gcd的贡献。我们定义f(i)为gcd==i的倍数时的贡献,那么f(i)=c(0,n)*0+c(1,n)*1+...c(n,n)*n ,这里的n为能够整除i的数的个数。然后利用容斥把gcd==i的贡献筛出来(这里无非就是要把其倍数处理掉~)。

然后结合c(1,n)+c(2,n)+....c(n,n)=2^n这个可以推出f(i)=n*2^(n-1)。然后倒着容斥一下(虽然自己看着别人的代码看了半天,这里还是装逼带过吧23333)。

ac代码:

#include<stdio.h>  
#define mod 1000000007  
#define LL long long  
LL cnt[1000005], sum[1000005];  
LL Pow(LL a, LL b)  
{  
    LL now;  
    now = 1;  
    while(b)  
    {  
        if(b%2)  
            now = now*a%mod;  
        a = a*a%mod;  
        b /= 2;  
    }  
    return now;  
}  
int main(void)  
{  
    LL ans, i, j, n, x;  
    scanf("%lld", &n);  
    for(i=1;i<=n;i++)  
    {  
        scanf("%lld", &x);  
        cnt[x]++;  
    }  
    ans = 0;  
    // 注意转换下题目意思 去枚举每个gcd的贡献
    for(i=1000000;i>=2;i--)  
    {  
        x = 0;  
        for(j=i;j<=1000000;j+=i)  
        {  
            sum[i] -= sum[j]; // 容斥 把倍数的结果去掉 
            x += cnt[j]; // 记录gcd为x的个数
        }  
        sum[i] += x*Pow(2, x-1)%mod;  //  这里的sum[i]为gcd==i的时候的贡献
        ans = ((ans+sum[i]*i)%mod+mod)%mod;  
    }  
    printf("%lld\n", ans);  
    return 0;  
}  

 

转载于:https://www.cnblogs.com/z1141000271/p/7419717.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值