首页 > 代码库 > [CF] 839.D

[CF] 839.D


题意;给出长度为n的序列a 若子序列b[1]..b[k]其gcd(b1..bk)>1 则贡献k*gcd(b1..bk)
n<=1e5,a[i]<=1e6,求所有贡献之和.
枚举gcd为i时对答案的贡献,贡献为i*(1*k[1]+2*k[2]+..m*k[m]) k[j]为子序列为gcd为i,长度为j的个数,令括号部分为f[i]
当i的倍数有n个时,贡献(包含重复)为i*(k=1~n)C(n,k)*k = n*2^(n-1)
扣掉重复部分f[pi](p>1)即可.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+20;
const int mod=1e9+7;
ll f[N],cnt[N],pw2[N];
int n,a[N];
int main()
{
    pw2[0]=1;
    for(int i=1;i<N;i++)
        pw2[i]=(pw2[i-1]*2ll)%mod;
    while(cin>>n)
    {
        memset(f,0,sizeof(f));
        int mx=0;
        ll ans=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),cnt[a[i]]++,mx=max(mx,a[i]);
        for(int i=mx;i>=2;i--)
        {
            ll tot=0;
            for(int j=i;j<=mx;j+=i)
                tot+=cnt[j];
            ll res=(tot*pw2[tot-1])%mod;//(i=1~n)C(n,i)*i = n*2^(n-1)
            for(int j=i+i;j<=mx;j+=i)
                res=(res-f[j]+mod)%mod;    
            f[i]=res;
            ans=(ans+(ll)i*f[i]%mod)%mod;    
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

[CF] 839.D