[Codeforces Round #428 DIV2D (CF839D)] Winter is here

来源:互联网 发布:天极软件中心 编辑:程序博客网 时间:2024/06/05 23:44

题意

给定一个数列ai,若子序列长度为k,最大公约数为gcd,定义子序列的权值为kgcd[gcd>1]。求所有子序列的权值和。
n2105,ai106,答案对109+7取模。

题解

考虑枚举gcd。设cntgcd的倍数的ai的个数。
gcd是一个质数时,那么这个gcd的贡献即为

gcd(1C1cnt+2C2cnt++cntCcntcnt)

由基础的组合数学知识得上式的结果为
gcd(cnt2cnt1)

gcd不是一个质数时,上式计算的贡献显然多了,它计算多的贡献是
x|gcdx(cnt2cnt1)

如果直接枚举因子减去多出的贡献,复杂度O(AA)的,不能接受。
从小到大枚举gcd,再将当前gcd的倍数都减去当前答案,或者预处理出GCD[gcd]=gcdx|gcdx,类似埃拉托斯特尼筛法复杂度O(AloglogA)

代码

/// by ztx/// blog.csdn.net/hzoi_ztx#include <bits/stdc++.h>#define Rep(i,l,r) for(i=(l);i<=(r);i++)#define rep(i,l,r) for(i=(l);i< (r);i++)#define Rev(i,r,l) for(i=(r);i>=(l);i--)#define rev(i,r,l) for(i=(r);i> (l);i--)#define Each(i,v)  for(i=v.begin();i!=v.end();i++)#define r(x)   read(x)typedef long long ll ;typedef double lf ;int CH , NEG ;template <typename TP>inline void read(TP& ret) {    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;    if (CH == '-') NEG = true , CH = getchar() ;    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;    if (NEG) ret = -ret ;}template<typename TP>inline bool MI(TP&a,const TP&b){return a>b?a=b,true:false;}template<typename TP>inline bool MA(TP&a,const TP&b){return a<b?a=b,true:false;}#define  kN  200010LL#define  mod  1000000007LL#define  kA  1000010LLinline void inc(int&a,const int&b) {a+=b;if(a>=mod)a-=mod;}inline void dec(int&a,const int&b) {a-=b;if(a<0)a+=mod;}int n, ans = 0, ma = 1;int cnt[kA], pow_2[kN], gcd[kA];int main() {    int i, j, now;    r(n);    Rep (i,1,n) r(j), cnt[j] ++ , MA(ma,j);    pow_2[0] = 1;    Rep (i,1,n) pow_2[i] = pow_2[i-1], inc(pow_2[i],pow_2[i-1]);    Rep (i,2,ma)        for (gcd[i]+=i, j=i<<1; j <= ma; j += i) dec(gcd[j],gcd[i]);    Rep (i,2,ma) {        for (now=0, j=i; j <= ma; j += i)            now += cnt[j];        if (!now) continue;        inc(ans,1LL*now*gcd[i]%mod*pow_2[now-1]%mod);    }    printf("%d\n", ans);    END: getchar(), getchar();    return 0;}
原创粉丝点击