zoukankan      html  css  js  c++  java
  • [SDOI2012] Longge的问题

    欧拉函数

    传送门:$>here<$


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

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


    $Solution$

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

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

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

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

    $my code$

    由于$n$较大,肯定不能筛。所以用通项公式$φ(n)=n*prodlimits_{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;
    }
  • 相关阅读:
    linux下链接静态链接库
    linux消息队列操作(转)
    android 模块编译,mm 命令
    关于函数里对指针赋值的问题
    Android内核和驱动篇Android内核介绍 (转)
    pthread属性使用(转)
    MOD_INC_USE_COUNT和MOD_DEC_USE_COUNT(转)
    linux下配置文件的读写
    从Linux程序中执行shell(程序、脚本)并获得输出结果(转)
    封装错误信息打印的函数
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9926168.html
Copyright © 2011-2022 走看看