[SDOI2012] Longge的问题

欧拉函数

传送门:$>here<$


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

数据范围:$n \leq 2^{32}$


$Solution$

设$f(x)$表示$gcd$为$x$的$i$有多少个,这样的话答案就可以被表示为$\sum\limits_{i|n}^{n}f(i)*i$

($gcd(i,n)$的取值一定是$n$的一个因子)

因此关键在于如何求出$f(x)$。由定义可得$f(x)=\sum\limits_{i=1}^{n}[gcd(i,n)=x]$,等价于$f(x)=\sum\limits_{i=1}^{\frac{n}{x}}[gcd(\dfrac{i}{x},\dfrac{n}{x})=1]$。其实也就是$f(x)=\sum\limits_{i=1}^{\frac{n}{x}}[gcd(i,\dfrac{n}{x})=1]$,那么就可以表示为$f(x)=φ(\dfrac{n}{x})$

所以答案也就是$\sum\limits_{i|n}^{n}φ(\dfrac{n}{i})*i$

$my \ code$

由于$n$较大,肯定不能筛。所以用通项公式$φ(n)=n*\prod\limits_{i=1}^{r}\dfrac{p_i-1}{p_i}$。由于枚举因子或质因子的复杂度都是$logn$的,所以总的复杂度应该是$O(log^2n)$

/*By DennyQi 2018*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
#define int ll
const int MAXN = 10010;
const int MAXM = 20010;
const int INF = 1061109567;
inline int Max(const int a, const int b){ return (a > b) ? a : b; }
inline int Min(const int a, const int b){ return (a < b) ? a : b; }
inline int read(){
    int x = 0; int w = 1; register char c = getchar();
    for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
    if(c == '-') w = -1, c = getchar();
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
}
int N,ans,tot,Lim;
inline int phi(int n){
    if(n == 1 || n == 2) return 1;
    int res = n;
    int lim = sqrt(n)+1;
    for(int i = 2; i <= lim && i*i<=n; ++i){
        if(n % i == 0){
            res = res / i * (i-1) ;
        }
        while(n%i==0) n/=i;
    }
    if(n>1) res = res / n * (n-1);
    return res;
}
signed main(){
    //freopen(".in","r",stdin);
    N = read();
    Lim = sqrt(N);
    for(int d = 1; d <= Lim; ++d){
        if(N % d == 0){
            if(d * d == N){
                ans += d * phi(N/d);
            }
            else{
                ans += d * phi(N/d) + (N/d) * phi(d);
            }
        }
    }
    printf("%lld", ans);
    return 0;
}

 

posted @ 2018-11-07 22:18  DennyQi  阅读(255)  评论(0编辑  收藏  举报