zoukankan      html  css  js  c++  java
  • 欧拉函数

    处理何种问题:用于求解[1,n]中有多少个数与n互质的个数。

     

    性能:单次查询时间复杂度为,打表的话有一个线性筛,时间复杂度为O(n)。

     

    原理

    可以先在1到n-1中找到与n不互质的数,然后把他们减掉

    比如φ(12)

    把12质因数分解,12=2*2*3,其实就是得到了2和3两个质因数

    然后把2的倍数和3的倍数都删掉

    2的倍数:2,4,6,8,10,12

    3的倍数:3,6,9,12

    本来想直接用12 - 12/2 - 12/3

    但是6和12重复减了

    所以还要把即是2的倍数又是3的倍数的数加回来 (>﹏<)

    所以这样写12 - 12/2 - 12/3 + 12/(2*3)

    这叫什么,这叫容斥啊,容斥定理听过吧

    比如φ(30),30 = 2*3*5

    所以φ(30) = 30 - 30/2 - 30/3 - 30/5 + 30/(2*3) + 30/(2*5) + 30/(3*5) - 30/(2*3*5)

    但是容斥写起来好麻烦( ̄. ̄)

    有一种简单的方法

    φ(12)   =   12*(1 - 1/2)*(1 - 1/3)                 =   12*(1 - 1/2 - 1/3 + 1/6)

    φ(30)   =   30*(1 - 1/2)*(1 - 1/3)*(1 - 1/5)   =   30*(1 - 1/2 - 1/3 - 1/5 + 1/6 + 1/10 + 1/15 - 1/30)

    你看( •̀∀•́ ),拆开后发现它帮你自动帮你容斥好

    所以φ(30)的计算方法就是先找30的质因数

    分别是2,3,5

    然后用30* 1/2 * 2/3 * 4/5就搞定了

    顺便一提,phi(1) = 1

    摘自:https://www.cnblogs.com/linyujun/p/5194170.html#undefined

     

    实现步骤:略,找的板子,来自上述网址

    输入样例解释

    输出样例解释

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    ///欧拉函数
    long long PHI(long long x)
    {
        long long ans = x;
        for(long long i = 2; i*i <= x; i++)
        {
            if(x % i == 0)
            {
                ans = ans / i * (i-1);
                while(x % i == 0)
                    x /= i;
            }
        }
        if(x > 1)
            ans = ans / x * (x-1);
        return ans;
    }
    ///欧拉表
    const int N =20000010 ;
    long long phi[N], prime[N];
    long long tot;///tot计数,表示prime[N]中有多少质数
    void Euler()
    {
        phi[1] = 1;
        for(long long i = 2; i < N; i ++)
        {
            if(!phi[i])
            {
                phi[i] = i-1;
                prime[tot ++] = i;
            }
            for(long long j = 0; j < tot && i*prime[j] < N; j ++)
            {
                if(i % prime[j])
                    phi[i * prime[j]] = phi[i] * (prime[j]-1);
                else
                {
                    phi[i * prime[j] ] = phi[i] * prime[j];
                    break;
                }
            }
        }
    }
    
    int main()
    {
        Euler();
        for(int i=1; i<=20; ++i) ///前20欧拉数的表
        {
            printf("%d:%lld
    ",i,phi[i]);
        }
        return 0;
    }
    /**
    1:1
    2:1
    3:2
    4:2
    5:4
    6:2
    7:6
    8:4
    9:6
    10:4
    11:10
    12:4
    13:12
    14:6
    15:8
    16:8
    17:16
    18:6
    19:18
    20:8
    */
    

      

  • 相关阅读:
    Java8新特性Stream详细教程
    自定义注解!绝对是程序员装逼的利器!!
    如何处理重复请求/并发请求的
    C#字符处理
    mysql 索引
    mysql事件【定时器】
    JS日期,金钱处理
    Controller中使用@Value无法获取属性值
    druid连接池的配置
    mybatiste报错java.lang.ClassCastException
  • 原文地址:https://www.cnblogs.com/l1l1/p/9837725.html
Copyright © 2011-2022 走看看