• 欧拉函数


    欧拉函数:φ(n)即在1~n中与n互质的数的个数φ(1) = 1, φ(2) = 1, φ(3) = 2,φ(4) = 2,φ(5) = 3,φ(6) = 2(即1、5)

    对于一个数N肯定等于它的质因子的指数和:N = p1^φ1 + p2^φ2 + ……+pk^φk。

    那么求该数的欧拉函数等于:φ(N) = N(1 - 1 / p1)(1 - 1 / p2)(1 - 1 / p3)……(1 - 1 / pk),比如φ(6) = 6 * 1 / 2 * 2 / 3 = 2。

    用容斥原理来证明:1 ~ N中与N互质的数的个数φ(N) 

    前置知识:N的质因子为p1, p2,……,pk, N = p1^φ1 + p2^φ2 + ……+pk^φk。被1整除的个数为n, 被2整除的个数为 n / 2, 被3整除的个数为 n / 3, ……,那么被前n个数整除的个数加起来:n * (1+1/2+1/3+1/4+...1/n) = n * (ln(n+1) + r), Euler近似地计算了r的值,约为0.5772156649。这个数字就是后来称作的欧拉常数

    1、从N中分别去掉它所有质因子p1、p2、……、pk的所有倍数

    φ(N)  = N - N / p1 - N / p2 - N / p3 - …… - N / pk; 比如6的质因子2、3, 去除2的倍数个数:6 / 2 = 3(2, 4, 6), 去除3的倍数个数:6 / 3 = 2(3,6)

    2、因为上面会多去除一次pi*pj的倍数,如上就多去除了2 * 3的倍数6,所以要加过来。

    φ(N)  = N - N / p1 - N / p2 - N / p3 - …… - N / pk + N / p1p2 + N / p1p3 + N / p2p3 + ……

    3、根据容斥原理,

    正中间的区域G又被抵消掉了,变成没有加进来,但是我们要把它去掉(因为p1p2p3质因子的乘积肯定与N不互质)

     φ(N)  = N - N / p1 - N / p2 - N / p3 - …… - N / pk + N / p1p2 + N / p1p3 + N / p2p3 + ……-N / p1p2p3 - N / p1p2p4-……+ N / p1p2p3p4……

     φ(N) = N(1 - 1 / p1)(1 - 1 / p2)(1 - 1 / p3)……(1 - 1 / pk)

    比较这两个式子,全部乘1后,可以得到N,-1 / p1乘以所有1后得到也是负数,即 -N/p1;-1/p1*-1/p2 = 所以1 / p1p2的常数项是正的。

    简单推论发现上面即是下面的展开项。

    *给定n个正整数aiai,请你求出每个数的欧拉函数。

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        int n;
        cin>>n;
        while(n--)
        {
            int x;
            cin>>x;
            int res = x;
            for(int i = 2;i <= x / i; i++)
            {
                if(x % i == 0)
                {
                    res = res / i * (i - 1);
                    while(x % i == 0) x /= i;
                }
            }
            if(x > 1) res = res / x * (x - 1);
            
            cout<<res<<endl;
        }
        
    }

    注意:本来这里是res = res * (1 - 1 / i) = res * (i - 1) / i;但这样写会出错,可能会导致某个地方无法整数

    要写成 res = res / i * (i - 1); res = res / x * (x - 1);

    筛法求欧拉函数:

    题目描述
    给定一个正整数n,求1~n中每个数的欧拉函数之和。
    数据范围:1≤n≤10^6

    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef unsigned long long LL;
    const int N = 1e6 + 10;
    int primes[N], phi[N], cnt;
    bool st[N];
    
    LL get_eulers(int n)
    {
        phi[1] = 1;
        for(int i = 2;i <= n; i ++)
        {
            if(!st[i])
            {
                primes[cnt++] = i;
                phi[i] = i - 1;
            }
                for(int j = 0;primes[j] <= n / i; j++)
                {
                    st[i * primes[j]] = true;
                    if(i % primes[j] == 0) 
                    {
                        phi[primes[j] * i] = primes[j] * phi[i];
                        break;
                    }
                    phi[primes[j] * i] = phi[i] * (primes[j] - 1);
                }
        }
        LL res = 0;
        for(int i = 1; i <= n; i++) res += phi[i];
        
        return res;
    }
    
    int main()
    {
        int n;
        cin>>n;
        
        cout<<get_eulers(n)<<endl;
        
        return 0;
    }

    1、首先对于指数i的欧拉函数:φ(i) = i - 1(前i - 1个数都与它互质)

    2、如果 i % p[j] == 0, 此时i是合数,且p[j]是i的最小质因子,那么φ(i * pj)的质因子与φ(i)的质因子完全相同,(1 - 1 / pj)已经在φ(i)中计算过了,只需要乘以一个pj就行了,那么φ(i) = i * (1 - 1 / p1)(1 - 1 / p2)……(1 - 1 / pk),φ(i * p[j]) = p[j] * φ(i)  ;

    3、如果i % p[j] != 0, p[j]是 i * p[j]的最小质因子,pj不包含在 i 的质因子当中。根据之前对线性筛的分析,这时候 i 和 pj肯定都是质数,且pj <= i.

    φ(i) = i * (1 - 1 / p1)(1 - 1 / p2)……(1 - 1 / pk),φ(i * p[j])比φ(i)多了一个质因子p[j], 所以要多乘以一个(1 - 1 / pj):

    φ(i * p[j]) = p[j] * i * (1 - 1 / p1)(1 - 1 / p2)……(1 - 1 / pk)(1 - 1 / pj) = (pj - 1)φ(i)。

    所以

    i % p[j] == 0 时:phi[primes[j] * i] = primes[j] * phi[i];
    i % p[j] != 0 时:phi[primes[j] * i] = (primes[j] - 1) * phi[i];
    于是得证。
  • 相关阅读:
    变量对象,作用域链,闭包,匿名函数,this关键字,原型链,构造器,js预编译,对象模型,执行模型,prototype继承
    iptables-snat-dnat-设置
    salt-ssh
    linux-vsftp
    网站申请HTTPS 访问
    shell 处理文件脚本
    last与lastb命令 读取的日志文件
    Linux-server-sshd
    Nginx 日志切割
    修改或隐藏服务器名称需要修改源码
  • 原文地址:https://www.cnblogs.com/longxue1991/p/12723308.html
Copyright © 2020-2023  润新知