[BZOJ]Longge的问题[SDOI2012]

题目背景

SDOi2012

题目描述

Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出$$\sum _{i=1} ^n gcd(i, N)$$。

输入输出格式

输入格式

一个整数,为N。

输出格式

一个整数,为所求的答案。

输入输出样例

输入样例
6
输出样例
15

说明

对于60%的数据,$$0<N \leq 2^{16}$$

对于100%的数据,$$0<N \leq 2^{32}$$

思路

数论

题意:求$$\sum _{i=1} ^n gcd(i,n)$$

设$$t(x)$$表示$$1到N中最大公约数为x的个数$$,即:

​ $$t(x)=\sum _{i=1} ^n [gcd(i,N)=x]=[gcd(i,\left \lfloor \frac{N}{x} \right \rfloor)=1]$$

​ $$ \therefore t(x)=\phi(\left \lfloor \frac{N}{x} \right \rfloor)$$

$$\sum {i=1} ^N gcd(i,N)=\sum {d|N} \sum {i=1} ^{\left \lfloor \frac{N}{d} \right \rfloor } (d \cdot \phi(\left \lfloor \frac{N}{d} \right \rfloor))=\sum {d|N}d \cdot \phi(\left \lfloor \frac{N}{d} \right \rfloor)$$

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;

ll n, ans = 0;

ll getphi(ll x)
{
    ll res = x;
    for (ll i = 2; i*i <= x; i++)
    {
        if (x%i==0)    res = res / i*(i - 1);
        while (x%i==0) x / = i;
    }
    if (x > 1)    res = res / x*(x - 1);
    return res;
}

int main()
{
    scanf("%lld", &n);
    ll i = 1;
    for (; i*i < n; i++)
    {
        if (n%i==0)    ans += i*getphi(n / i) + getphi(i)*(n / i);
    }
    if (i*i == n)    ans += i*getphi(i);
    printf("%lld\n", ans);
}

results matching ""

    No results matching ""