[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 }