codeforces 864D 莫比乌斯反演

来源:互联网 发布:和服羽织淘宝 编辑:程序博客网 时间:2024/06/05 09:20

简略题意:给出n个数,任选k个数,若gcd(a1,a2...ak)>1, 他们对答案的贡献是kgcd(a1,a2...ak),问所有可能的方案的总贡献是多少。

枚举gcd,那么我们要计算的就是当前gcd对答案的贡献。
f(i)为所有方案中gcd=i对答案的贡献,F(i)表示i|gcd对答案的贡献。
假若有x个数为i的倍数,则:
F(i)=1C(x,1)+2C(x,2)+3C(x,3)+...+xC(x,x)
=x(C(x1,1)+C(x1,2)+C(x1,3)+...+C(x1,x1))=x2x1
f(i)=maxvi=1i|dμ(d/i)F(d)

#include <bits/stdc++.h>using namespace std;typedef long long LL;const LL maxn = 1100000;const LL mod = 1e9+7;LL mul(LL a, LL b) {    a *= b;    a = a % mod;    a += mod;    a %= mod;    return a;}LL add(LL a, LL b) {    a += b;    if(a >= mod) a-=mod;    return a;}bool tag[maxn];LL p[maxn/10];LL mob[maxn]; //莫比乌斯线性筛LL cnt;void GetPrime(){    cnt = 0;    mob[1] = 1;    for(LL i = 2; i < maxn; i++){        if(!tag[i]) {            p[cnt++] = i;            mob[i] = -1;        }        for(LL j = 0; j < cnt && p[j] * i < maxn; j++){            tag[i * p[j]] = 1;            if(i % p[j] == 0) {                mob[i*p[j]] = 0;                break;            }            mob[i*p[j]] = -mob[i];        }    }}LL F[maxn], f[maxn];struct ASSWECAN {    LL n;    LL cnt[maxn];    LL pow2[maxn];    LL ans[maxn];    void solve() {        scanf("%d", &n);        for(LL i = 1; i <= n; i++) {            LL v;            scanf("%d", &v);            cnt[v]++;        }        GetPrime();        pow2[0] = 1;        for(LL i = 1; i <= 1000000; i++) pow2[i] = mul(pow2[i-1], 2);        for(LL i = 2; i <= 1000000; i++) {            LL s = 0;            for(LL j = i; j <= 1000000; j+=i) s += cnt[j];            if(s) {                F[i] = mul(s, pow2[s-1]);            }        }        for(LL i = 1; i <= 1000000; i++) {            for(LL j = i; j <= 1000000; j+=i)                f[i] = add(mul(mob[j/i], F[j]), f[i]);        }        LL res = 0;        for(LL i = 2; i <= 1000000; i++)            res = add(res, mul(f[i], i));        printf("%lld\n", res);    }} solver;int main(){    solver.solve();    return 0;}
原创粉丝点击