Description
Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)。
Input
一个整数,为N。
Output
一个整数,为所求的答案。
Sample Input
6
Sample Output
15
HINT
【数据范围】
对于60%的数据,0 < N<=2^16。
对于100%的数据,0 < N<=2^32。
传送门
刷水有益身心~
很容易想到枚举某一个数字作为gcd(i,n),
假设这个数字为x
满足
gcd(i,n)=x
的对数为y,那么贡献就是x*y。
那么我们知道x一定是n的约数,所以枚举x的过程只用枚举n的约数就好了,
时间复杂度O(
n‾‾√
)
那么怎么求出y呢?
看到满足
gcd(i,n)=x
的所有i,一定满足:
i%x=0n%x=0gcd(i/x,n/x)=1
……所以很明显啦,和n/x的所有数,再乘上x,和n的gcd一定是x。。
那么求个欧拉函数就好啦。。
水题水题,多说无益= v =
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int
MAX=(1<<16);
int pcnt;
ll prime[MAX/10];
bool notprime[MAX];
void Get_Prime(){
notprime[1]=1,pcnt=0;
for (int i=2;i<MAX;i++){
if (!notprime[i]) prime[++pcnt]=i;
for (int j=1;j<=pcnt;j++){
if (prime[j]*i>=MAX) break;
notprime[prime[j]*i]=1;
if (!(i%prime[j])) break;
}
}
}
ll phi(ll x){
int j=1;ll t1=x;
while (j<=pcnt && x!=1){
if (!(x%prime[j])){
t1=t1/prime[j]*(prime[j]-1);
while (!(x%prime[j])) x/=prime[j];
}
j++;
}
if (x!=1) t1=t1/x*(x-1);
return t1;
}
int main(){
Get_Prime();
ll n;
scanf("%lld",&n);
ll tmp=sqrt(n),ans=0LL;
for (ll i=1LL;i<=tmp;i++)
if (!(n%i)){
ans+=i*phi(n/i);
if (n/i!=i) ans+=(n/i)*phi(i);
}
printf("%lld\n",ans);
return 0;
}