Codeforces 839D Winter is here

转载请注明出处,谢谢http://blog.csdn.net/bigtiao097?viewmode=contents

题意

给一个长度为n (1n200000) 序列a (1ai1000000) ,对于某个子序列 ai1ai2ai3aik ,长度为k,其中 i1<i2<i3<<ik ,如果 gcd(ai1ai2ai3aik)>1 ,则称这个子序列为一个clan,这个clan的strength为 kgcd(ai1ai2ai3aik) ,求所有的clan的strength之和

思路

枚举gcd的值x,对于每一个x,统计一下在序列中有多少个元素时x的倍数,这里可以开一个桶,将读入序列存入,这样可以将复杂度降至 O(nlog(n)) ,设有m个元素是x的倍数,则这些元素对答案的贡献为

x×[1×C1m+2×C2m++m×Cmm]

这个式子的值为 xm2m1
但是这样还有一个问题就是,比如说x=2时,假设数列中有元素4、8,这样4和8的gcd为4而不是2,我们应该想办法去掉这种情况具体做法如下:
在枚举到x的时候,我们统计出m,计算出 m2m1 后,应该枚举x的倍数减去相应的值,这就要求我们在枚举x的时候需要倒着枚举,这样才能保证我们枚举到x的时候,x的倍数都已经计算过了


具体代码如下:
Result:Accepted    Memory: 13600 KB   Time : 249 ms

#include<cstdio>
const int maxn=1e6+5;
const int mod =1e9+7;
int n,x,ans;
int pow[maxn],a[maxn],f[maxn];
int main()
{
    scanf("%d",&n);
    pow[0] = 1;
    for(int i=1; i<=n; i++)
        pow[i]=2*pow[i-1]%mod;
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&x);
        a[x]++;
    }
    for(int i=maxn-1; i>1; i--)
    {
        x = 0;
        for(int j=i; j<maxn; j+=i)
            x+=a[j];
        if(x)
        {
            f[i]=1LL*x*pow[x-1]%mod;
            for(int j=i+i; j<maxn; j+=i)
                f[i]=(f[i]-f[j]+mod)%mod;
            ans=(1LL*f[i]*i+ans)%mod;
        }
    }
    printf("%d",ans);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值