[BZOJ3560]DZY Loves Math V(欧拉函数)

https://www.cnblogs.com/zwfymqz/p/9332753.html

由于欧拉函数是积性函数,可以用乘法分配律变成对每个质因子分开算最后乘起来。再由欧拉函数公式和分配律发现就是等比数列求和问题,特判下1的问题就好了。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 typedef long long ll;
 5 using namespace std;
 6 
 7 const int mod=1e9+7;
 8 int n,x,cnt,tot,ans=1,sm[110],p[3510],b[3510];
 9 struct P{ int x,y; }a[800010];
10 bool cmp(const P &a,const P &b){ return a.x<b.x || (a.x==b.x && a.y<b.y); }
11 
12 int ksm(int a,int b){
13     int res=1;
14     for (; b; a=1ll*a*a%mod,b>>=1)
15         if (b & 1) res=1ll*res*a%mod;
16     return res;
17 }
18 
19 void Fac(int x){
20     for (int i=1; p[i]*p[i]<=x; i++)
21         if (x%p[i]==0){
22             int s=0;
23             while (x%p[i]==0) x/=p[i],s++;
24             a[++cnt]=(P){p[i],s};
25         }
26     if (x>1) a[++cnt]=(P){x,1};
27 }
28 
29 void init(int n){
30     rep(i,2,n){
31         if (!b[i]) p[++tot]=i;
32         for (int j=1; j<=tot && i*p[j]<=n; j++){
33             b[i*p[j]]=1;
34             if (i%p[j]==0) break;
35         }
36     }
37 }
38 
39 int main(){
40     freopen("bzoj3560.in","r",stdin);
41     freopen("bzoj3560.out","w",stdout);
42     scanf("%d",&n); init(3500);
43     rep(i,1,n) scanf("%d",&x),Fac(x);
44     sort(a+1,a+cnt+1,cmp);
45     for (int i=1,j; i<=cnt; i=j+1){
46         for (j=i; j<cnt && a[j+1].x==a[j].x; j++);
47         sm[0]=1; int tmp=1;
48         rep(k,1,a[j].y) sm[k]=1ll*sm[k-1]*a[i].x%mod;
49         rep(k,1,a[j].y) sm[k]=(sm[k-1]+sm[k])%mod;
50         rep(k,i,j) tmp=1ll*tmp*sm[a[k].y]%mod;
51         tmp=1ll*(tmp-1)*(a[i].x-1)%mod*ksm(a[i].x,mod-2)%mod+1;
52         ans=1ll*ans*tmp%mod;
53     }
54     printf("%d\n",ans);
55     return 0;
56 }

 

posted @ 2019-01-19 09:25  HocRiser  阅读(163)  评论(0编辑  收藏  举报