BZOJ3560:DZY Loves Math V 数学
思路:
首先我们需要知道欧拉函数的计算方法:
\[n=p_1^{q_1}p_2^{q_2}...p_m^{q_m}\rightarrow\phi(n)=n\frac{p_1-1}{p_1}\frac{p_2-1}{p_2}...\frac{p_m-1}{p_m}\]
\[\phi(n)=p_1^{q_1}\frac{p_1-1}{p_1}p_2^{q_2}\frac{p_2-1}{p_2}...p_m^{q_m}\frac{p_m-1}{p_m}\]
这证明我们可以将所有的质因数分开考虑.
我们对于所有质因数计算其贡献,然后乘到一起.(这东西维护一个前缀和就行了)
#include<cstdio> #include<cstring> #include<cctype> #include<iostream> #include<algorithm> #include<vector> using namespace std; #define N 10000010 int p[N/10],ins[N],cnt;bool notp[N];vector<int>v[N/10]; inline void pre(){ register int i,j; for(i=2;i<=10000000;++i){ if(!notp[i])p[++cnt]=i,ins[i]=cnt; for(j=1;j<=cnt&&i*p[j]<=10000000;++j){ notp[i*p[j]]=1; if(i%p[j]==0)break; } } } static const int mod=(1e9)+7; inline int ksm(int x,int y){ int t=x,res=1;for(;y;y>>=1,t=(long long)t*t%mod)if(y&1)res=(long long)res*t%mod;return res; } inline int inv(int x){ return ksm(x,mod-2); } inline void inc(int&x,int y){ if((x+=y)>=mod)x-=mod; } int seq[1000010],num;vector<int>vv[1000010]; int pref[40]; int main(){ pre(); int n;scanf("%d",&n);register int i,j,k; int x,nowadd; while(n--){ scanf("%d",&x);if(x==1)continue; for(i=1;i<=cnt&&p[i]*p[i]<=x;++i){ nowadd=0;while(x%p[i]==0)++nowadd,x/=p[i]; if(nowadd)v[i].push_back(nowadd); }if(x)v[ins[x]].push_back(1); } for(i=1;i<=cnt;++i)if((int)v[i].size()!=0){ seq[++num]=p[i]; for(j=0;j<(int)v[i].size();++j)vv[num].push_back(v[i][j]); } if(num==0)puts("1"); else{ int res=1,Mx,mi,tans; for(k=1;k<=num;++k){ for(Mx=0,i=0;i<vv[k].size();++i)Mx=max(Mx,vv[k][i]); for(pref[0]=1,mi=seq[k],i=1;i<=Mx;++i,mi=(long long)mi*seq[k]%mod)inc(pref[i]=pref[i-1],mi); for(tans=1,i=0;i<vv[k].size();++i)tans=(long long)tans*pref[vv[k][i]]%mod; tans=(long long)(tans+mod-1)*(seq[k]-1)%mod; tans=(long long)tans*inv(seq[k])%mod; res=(long long)res*(tans+1)%mod; } printf("%d",res); } return 0; }