求∑gcd(i, N) 1<=i <=N,两种做法
第一种做法:
由gcd(i,n)=k
=> gcd(i/k,n/k)=1
即满足gcd(i,n)=k 的i的个数应为<n/k且和n/k互质的数的个数,即eular(n/k)
然后依次枚举n的约束,累加eular(n/k)
枚举的时候注意优化
#include<stdio.h>
#include<string.h>
#include<math.h>
#define ll long long
#define MAXN 50005
bool isprim[MAXN];
ll prim[MAXN];
ll cnt;
void getprim()
{
cnt=0;
for(ll i=2;i<MAXN;i++)
{
if(!isprim[i]) prim[cnt++]=i;
for(ll j=0;j<cnt&&prim[j]*i<MAXN;j++)
{
isprim[i*prim[j]]=true;
if(i%prim[j]==0) break;
}
}
}
ll eular(ll n)
{
ll rea=n;
for(ll i=0;i<cnt&&prim[i]*prim[i]<=n;i++)
{
if(n%prim[i]==0)
{
rea=rea-rea/prim[i];
while(n%prim[i]==0)
n/=prim[i];
}
}
if(n>1)
rea=rea-rea/n;
return rea;
}
int main()
{
getprim();
ll n;
while(scanf("%lld",&n)!=EOF)
{
ll ans=0;
for(ll i=1;i*i<=n;i++)
if(n%i==0)
{
ans+=i*eular(n/i);
if(n!=i*i)
ans+=n/i*eular(i);
}
printf("%lld\n",ans);
}
return 0;
}
第二种方法:考虑到gcd(i,n)是一个积性函数,即gcd(i,n)=gcd(i,a*b)=gcd(i,a)*gcd(i,b),ab互质
由于积性函数的和函数也是积性函数(定理),则所求函数f(n)=∑gcd(i, n) 1<=i <=n也是一个积性函数
可得f(n)=∑(p*phi(n/p)),p是n的约数,原理和第一种方法类似
考虑f(p^k),p为素数
f(p^k)=∑p^i*eular(p^(k-i))
利用定理eular(p^k)=p^k-p^(k-1)将上式展开化简可得:f(p^k)=k*p^k - k*p^(k-1) + p^k
于是将n进行素因数分解:f(n)=f(p1^k1)*f(p2^k2)......挨个进行处理就行了
#include<stdio.h>
#include<string.h>
#include<math.h>
#define ll long long
int main()
{
ll n;
while(scanf("%lld",&n)!=EOF)
{
ll ans=1;
for(ll i=2;i*i<=n;i++)
{
if(n%i==0)
{
ll x=1,k=0;
while(n%i==0)
{
n/=i;
x*=i;
k++;
}
ans*=(k+1)*x-k*x/i;
}
}
if(n>1)
ans*=2*n-1;
printf("%lld\n",ans);
}
return 0;
}