Description
Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)。
Input
一个整数,为N。
Output
一个整数,为所求的答案。
Sample Input
6
Sample Output
15
HINT
【数据范围】
对于60%的数据,0
Source
round1 day1
先贴一个hzwer的,感觉说的好有道理。
枚举n的约数k,令s(k)为满足gcd(m,n)=k,(1<=m<=n)m的个数,则ans=sigma(k*s(k)) (k为n的约数)
因为gcd(m,n)=k,所以gcd(m/k,n/k)=1,于是s(k)=euler(n/k)
这是从意思上理解…
如果从式子上理解的话
∑i=1ngcd(i,n)
=∑i=1n∑d|gcd(i,n)ϕ(d)
=∑i=1n∑d|i d|nϕ(d)
到这里都是显然的。因为i是枚举的1到n,d是枚举的i和n的公因数。单独考虑d,d对答案有贡献当i是d及d的倍数的时候,这样的i一共有 n/d 个。
所以最终结果就是
∑d|nϕ(d)∗nd
这样对于n,质因数分解,再单独计算欧拉函数,复杂度 O((n)−−−√)
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int SZ = 1000010;
typedef long long LL;
LL phi(LL n)
{
LL ans = n;
LL m = sqrt(n);
for(int i = 2;i <= m;i ++)
{
if(n % i == 0)
{
ans -= ans / i;
while(n % i == 0) n /= i;
}
}
if(n > 1) ans -= ans / n;
return ans;
}
int main()
{
LL n;
scanf("%lld",&n);
LL ans = 0;
for(int i = 1;i <= sqrt(n);i ++)
{
if(n % i == 0)
{
ans += i * phi(n / i);
if(n / i != i) ans += phi(i) * (n / i);
}
}
printf("%lld",ans);
return 0;
}