【bzoj2705】[SDOI2012]Longge的问题 欧拉函数

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=1nd|gcd(i,n)ϕ(d)

=i=1nd|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
#include
#include
#include
#include
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;
}

你可能感兴趣的:(===数学相关===,欧拉函数)