极大团java_Codeforces 839D Winter is here(容斥原理)

【题目大意】

给出一些数,求取出一些数,当他们的GCD大于0时,将数量乘GCD累加到答案上,

求累加和。

【题解】

我们枚举GCD,统计为其倍数的数字数量,先假定其能组成的集合数为贡献,

但是我们发现在统计的过程中有多余统计的部分,比如4和8是2的倍数,

然而它们的GCD等于4,所以我们对于每个集合数的贡献要减去所有其倍数的集合数的贡献,

倒着容斥即可。

【代码】

#include

#include

using namespace std;

const int N=1000010,MOD=1e9+7;

int n,ans=0,w[N],dp[N],pw[N],mx;

int main(){

scanf("%d",&n);

for(int i=pw[0]=1;i<=n;i++)pw[i]=2*pw[i-1]%MOD;

for(int i=1,x;i<=n;i++)scanf("%d",&x),mx=max(x,mx),w[x]++;

for(int i=mx;i>1;i--){

int t=0;

for(int j=i;j<=mx;j+=i)t+=w[j];

if(!t)continue;

dp[i]=1LL*t*pw[t-1]%MOD;

for(int j=i+i;j<=mx;j+=i)dp[i]=(dp[i]-dp[j]+MOD)%MOD;

ans=(1LL*dp[i]*i+ans)%MOD;

}printf("%d\n",ans);

return 0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值