BZOJ3560 : DZY Loves Math V

因为欧拉函数是非完全积性函数,所以可以考虑对每个数进行分解质因数,将每个质数的解乘起来即可。

对于一个质数$p$,设它在各个数中分别出现了$b_1,b_2,...b_n$次,那么由生成函数和欧拉函数的性质得,它对答案的贡献为:

[(prod_{i=1}^nfrac{p^{b_i+1}-1}{p-1}-1) imesfrac{p-1}{p}+1]

#include<cstdio>
const int N=10000010,P=1000000007;
int n,m,i,j,a[100010],tot,p[N],v[N],cnt[N],r[N],f[N],ans=1;
inline void divide(int n){
  tot=0;
  while(n>1){
    if(!cnt[v[n]])p[tot++]=v[n];
    cnt[v[n]]++,n/=v[n];
  }
  for(int i=0;i<tot;i++){
    int j=p[i],t=j;
    while(cnt[j])t=1LL*t*j%P,cnt[j]--;
    f[j]=1LL*(t-1)*r[j-1]%P*f[j]%P;
  }
}
int main(){
  scanf("%d",&n);
  for(i=1;i<=n;i++){
    scanf("%d",&a[i]);
    if(a[i]>m)m=a[i];
  }
  for(r[0]=r[1]=1,i=2;i<=m;i++){
    r[i]=(-1LL*r[P%i]*(P/i)%P+P)%P;
    if(!v[i])p[tot++]=v[i]=i,f[i]=1;
    for(j=0;j<tot;j++){
      if(i*p[j]>m)break;
      v[i*p[j]]=p[j];
      if(i%p[j]==0)break;
    }
  }
  for(i=1;i<=n;i++)divide(a[i]);
  for(i=2;i<=m;i++)if(v[i]==i)ans=(1LL*(f[i]+P-1)*(i-1)%P*r[i]+1)%P*ans%P;
  return printf("%d",ans),0;
}

  

原文地址:https://www.cnblogs.com/clrs97/p/5060171.html