BZOJ3560 DZY Loves Math V(欧拉函数)

  对每个质因子分开计算再乘起来。使用类似生成函数的做法就很容易统计了。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 100010
#define M 10000010
#define P 1000000007
int n,a[N],prime[M>>3],id[M],v[M>>3],inv[M],cnt=0,ans=1;
bool flag[M];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj3560.in","r",stdin);
    freopen("bzoj3560.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read();
    for (int i=1;i<=n;i++) a[i]=read();
    inv[1]=1;
    for (int i=2;i<=M-10;i++)
    {
        inv[i]=P-1ll*(P/i)*inv[P%i]%P;
        if (!flag[i]) prime[++cnt]=i,id[i]=cnt,v[cnt]=1;
        for (int j=1;j<=cnt&&prime[j]*i<=M-10;j++)
        {
            flag[prime[j]*i]=1;
            if (i%prime[j]==0) break;
        }
    }
    for (int i=1;i<=n;i++)
    {
        int x=a[i];
        for (int j=1;flag[x];j++)
        if (x%prime[j]==0)
        {
            int tot=1;
            while (x%prime[j]==0) tot=(1ll*tot*prime[j]+1)%P,x/=prime[j];
            v[j]=1ll*v[j]*tot%P;
        }
        if (x>1) v[id[x]]=1ll*v[id[x]]*(x+1)%P;
    }
    for (int i=1;i<=cnt;i++)
    if (v[i]>1) ans=1ll*ans*(1ll*(v[i]-1)*(prime[i]-1)%P*inv[prime[i]]%P+1)%P;
    cout<<ans;
    return 0;
}

 

posted @ 2018-09-25 18:50  Gloid  阅读(144)  评论(0编辑  收藏  举报