Poj 2480

,1<=x<=n

可转化为n的每一个约数,乘以,1~n内与n的最大公约数为此约数个数,再求和。

  1. 求n的约数。
  2. 求个数。设a为n的一个约数,求满足gcd(x,n)=d,x的个数

    gcd(x/d,n/d)=1,所以乘法群n/d的规模为phi(n/d),即x有phi(n/d)个

    求n的约数

继续简化问题

设n=

 

设f(n)为

所以f() =

         =*(1-1/pk)+ *(1-1/pk)+…+*(1-1/pk)+

         =ek(1-1/pk)+

Gcd为积性函数,所以和函数f也为积性函数

f(n)= =n*…(ek (1-1/pk)+1)*…

方法一:47MS,每次循环都求素数因子

#include <iostream>

#include <stdio.h>

using namespace std;

long long eu(long long n)

{

long long ret=n,e,i;

for(i=2;i*i<=n;i++)

{

if(n%i==0)

{

e=0;

while(n%i==0){n/=i;e++;}

ret=ret/i*e*(i-1)+ret;

}

}

if(n>1)

ret=ret/n*(2*n-1);

return ret;

}

int main()

{

long long n;

freopen("in.txt","r",stdin);

while(scanf("%lld",&n)!=EOF)

printf("%lld\n",eu(n));

return 0;

}

方法二,16ms,打印素数表

#include <iostream>

#include <stdio.h>

using namespace std;

 

const int MAX=65535;

bool prime[MAX+10];

int a[MAX+10];

void getprime()

{

long long i,j;

int cnt=1;

prime[0]=prime[1]=0;

for(i=2;i<=MAX;i++)

prime[i]=1;

for(i=2;i<=MAX;i++)

{

 

if(prime[i])

{

a[cnt++]=i;

for(j=i*i;j<=MAX;j+=i)

prime[j]=0;

 

}

 

}

 

}

 

long long eu(long long n)

{

long long ret=n,e,i;

for(i=1;a[i]!=0&&a[i]*a[i]<=n;i++)

{

if(n%a[i]==0)

{

e=0;

while(n%a[i]==0){n/=a[i];e++;}

ret=ret/a[i]*e*(a[i]-1)+ret;

}

}

 

if(n>1)

ret=ret/n*(2*n-1);

return ret;

}

int main()

{

long long n;

getprime();

freopen("in.txt","r",stdin);

while(scanf("%lld",&n)!=EOF)

printf("%lld\n",eu(n));

return 0;

}

原文地址:https://www.cnblogs.com/inpeace7/p/2389418.html