思路:枚举因子,gcd(n,k)=x , 那么gcd( n/x , k/x)=1, 利用欧拉函数求解Euler(n/x) , 再利用公式 即可求解
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=50;
int fac[maxn],p[maxn],cnt=0,n;
LL sum=0;
int pow(int a,int b)
{
int ans=1;
while(b)
{
if(b&1) ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
LL Euler(LL k)
{
if(k==1) return 1;
LL ans=k;
for(LL i=2;i<=floor(sqrt(k) + 0.5); i++)
{
if( k % i == 0) {
ans/=1l*i;
ans*=1l*(i-1);
while(k%i==0) k/=1l*i;
}
if(k==1) break;
}
if(k!=1) {
ans/=1l*k;
ans*=1l*(k-1);
}
return ans;
}
void dfs(int pos,int son)
{
if(pos==cnt) {
//cout<<n<<endl;
//cout<<son<<endl;
sum+=Euler( 1l*n/son ) * son;
//cout<<Euler(n/son)<<endl;
//cout<<sum<<endl;
return;
}
for(int i=0;i<=p[pos];i++)
{
dfs(pos+1,son*pow( fac[pos], i ) );
}
return;
}
int main()
{
//cout<<Euler(3)<<endl;
scanf("%d",&n);
int k=n;
for(int i=2;i<=floor(sqrt(n)+0.5);i++)
{
if(n%i==0) {
fac[cnt]=i;
p[cnt]=0;
while(n%i==0) {
p[cnt]++;
n/=i;
}
cnt++;
}
if(n==1) break;
}
if(n!=1) {
fac[cnt]=n;
p[cnt]=1;
cnt++;
}
n=k;
/*for(int i=0;i<cnt;i++)
{
printf("%d %d\n",fac[i],p[i]);
}*/
//枚举因子
dfs(0,1);
//cout<<"200"<<endl;
printf("%lld\n",sum);
return 0;
}