题意:
给出一个序列,求其中所有 gcd 大于 1 的子序列乘以序列长度之和。
分析:
利用埃氏筛的原理,求出在数组中有多少i的倍数,假设有x个数是i的倍数,则这x个i的倍数的排列有x * 2 ^ (x-1)
PS:1*C(x,1)+2*C(x,2)*...+x*C(x,x),故排列有 x * 2 ^ (x-1)个。但是对于2,4,8来说,4和8都是2的倍数,但gcd(4,8) = 4,
故在计算2的倍数的时候要去掉这种排列。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const int mod=1e9+7;
int a[maxn];
ll d[maxn],f[maxn];
void init(){
f[0]=1;
for(int i=1;i<maxn;i++){
f[i]=2*f[i-1]%mod;
}
}
int main(){
init();
int n;
scanf("%d",&n);
int t;
for(int i=0;i<n;i++){
scanf("%d",&t);
a[t]++;
}
ll ans=0;
for(int i=maxn-1;i>1;i--){
ll x=0;
//计算i的倍数有多少个
for(int j=i;j<maxn;j+=i){
x+=a[j];
}
if(x){
d[i]=x*f[x-1]%mod;
for(int j=i+i;j<maxn;j+=i){
d[i]=(d[i]-d[j]+mod)%mod;
}
}
ans=(ans+1ll*i*d[i])%mod;
}
printf("%lld\n",ans);
return 0;
}