版权声明:原来这里可以拿来卖萌ヽ(・∀・)ノ https://blog.csdn.net/u012345506/article/details/86547178
考虑枚举买哪一张,那么买第
张产生的贡献为:
注意到当
时,后面那一串时等价于:
所以我们只需要分析
时的情况,此时我们需要求出
,即不包含
且
的集合总数。
容易想到其和
可以在
间转换:
只需要将
改为
,同时将
的因数产生的贡献消去即可。
这么做计算最终结果产生的复杂度应当为 ,为了优化,对于因数,可以只计算 的部分,当 时,这么做在最坏的情况下产生的因子数只有 不到。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<climits>
#include<cstdio>
#include<cmath>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))
//--Container
//--
typedef long long ll;
const ll md=1e9+7;
const int up=1e7;
int pr[up+10],mp[up+10];bool bd[up+10];int mu[up+10],pn,n;
void _sie(){
int i,j,k,d,t;for(pn=0,mu[1]=1,i=2;i<=up;++i){
if(!bd[i])pr[++pn]=i,mu[i]=-1,mp[i]=i;
for(j=1;j<=pn&&(ll)pr[j]*i<=up;++j){
bd[pr[j]*i]=1,mu[pr[j]*i]=-mu[i],mp[pr[j]*i]=pr[j];
if(!(i%pr[j])){
mu[pr[j]*i]=0;
break;
}
}
}
for(i=1;i<=up;++i)if(mu[i]<0)mu[i]+=md;
};
int _shak(int n,int*cr,int*crn){
int i,j,k,d,r=1,t,zs[40],zn=0;for(;n>1;){
if(cr)zs[zn++]=mp[n];
r*=mp[n],t=mp[n];for(;mp[n]==t;n/=mp[n]);
}
if(cr){
for(i=0;i<(1<<zn);++i){
for(d=1,j=0;j<zn;++j)if(i&(1<<j))d*=zs[j];
cr[i]=d;
}
*crn=i;
}
return r;
};
int sm[up+10],_2p[500010],ccr[10010];ll drs;
void _init(){
int i;for(_2p[0]=1,i=1;i<=500000;++i)_2p[i]=(_2p[i-1]+_2p[i-1])%md;
};
void _upd(int n){
int i,j,k,d,r=_shak(n,ccr,&d);
for(i=0;i<d;++i)sm[ccr[i]]++;
};
void _drs(){
int i,j;for(i=1;i<=up;++i)if(mu[i]!=0)drs=(drs+(ll)mu[i]*(md-1+_2p[sm[i]])%md)%md;
};
ll _cl(int x,ll drs){
ll rs=0;int i,j,k,d,t=_shak(x,ccr,&d);
for(i=0;i<d;++i){
drs=(drs+md-(ll)mu[ccr[i]]*(md-1+_2p[sm[ccr[i]]])%md)%md;
drs=(drs+(ll)mu[ccr[i]]*(md-1+_2p[sm[ccr[i]]-1])%md)%md;
}
drs=(md+_2p[n-1]-1-drs)%md;
for(i=1;i<d;++i){
drs=(drs+(ll)mu[ccr[i]]*(md-1+_2p[sm[ccr[i]]-1]))%md;
}
return drs;
};
int ar[500010];
void cl(){
int i,j,k,d,t;ll rs=0;scanf("%d",&n);for(i=1;i<=n;scanf("%d",&ar[i++]));
for(i=1;i<=n;_upd(ar[i++]));drs=0;_drs();for(i=1;i<=n;++i){
rs=(rs+_cl(ar[i],drs))%md;
}
printf("%lld\n",rs);
};
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
_sie();_init();cl();
return 0;
};