bzoj2075[SDOI2012]Longge的问题
传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2705
思路:首先要求的是Σgcd(i,n)(1<=i<=n)
于是可以化成ΣΣd*[gcd(i,n/d)==1] (d|n,1<=i<=n)//中括号表示其中的表达式成立则为1,否则为0
把d提出来
Σd*Σ[gcd(i,n/d)==1] (d|n,1<=i<=n)
右边的不就是phi(欧拉函数)吗
于是有Σd*phi(n/d) (d|n)
因为d和phi(d)为积性函数,所以f(d)=Σd*phi(n/d) (d|n)是积性函数
于是先考虑求f(p^a)(p为质数)
phi(p^a)=p^a-p^(a-1)
f(p^a)=p^0*(p^a-p^(a-1))+p^1*(p^(a-1)-p^(a-2))+....+p^a(最后的p^a有点特别要注意)
=p^(a-1)*(p*a-a+p)
于是只要质因数分解,分别求出再相乘即可。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; ll n,ans; ll qpow(int a,int b){ ll res=1; for (int j=a;b;b>>=1,j=j*j) if (b&1) res*=j; return res; } int main(){ //printf("%lld\n",qpow(2,30)); scanf("%lld",&n),ans=1; for (int i=2;1ll*i*i<=n;i++){ if (n%i==0){ int cnt=0; while (n%i==0) n/=i,cnt++; ans*=qpow(i,cnt-1)*(i*cnt-cnt+i); } } if (n!=1) ans*=(2*n-1); printf("%lld\n",ans); return 0; }