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

    本博客转自:https://www.cnblogs.com/linyujun/p/5194170.html

    欧拉函数,用φ(n)表示

    欧拉函数是求小于等于n的数中与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

     1 int phi(int x){
     2     int ans = x;
     3     for (int i=2;i*i<=x;i++){
     4         if (x % i == 0){
     5             ans = (ans / i * (i - 1) );
     6             while (x % i == 0)
     7                 x /= i;
     8         }
     9     }
    10     if (x>1){ // 防止x是质数
    11         ans = (ans / x * (x-1) );
    12     }
    13     return ans;
    14 }

    这个的复杂度是O(√n),如果要你求n个数的欧拉函数,复杂度是O(n√n),这也太慢了

    有更快的方法

    跟埃筛素数差不多

     1 int phi[N];
     2 
     3 void Euler(){
     4     phi[1] = 1;
     5     for (int i=2;i<N;i++){
     6         if (!phi[i]){
     7             for (int j=i;j<N;j+=i){
     8                 if (!phi[j])
     9                     phi[j] = j;
    10                 phi[j] = phi[j] / i * (i - 1);
    11             }
    12         }
    13     }
    14 }

    另一种,比上面更快的方法

    需要用到如下性质

    p为质数

    1. phi(p)=p-1   因为质数p除了1以外的因数只有p,故1至p的整数只有p与p不互质 

    2. 如果i mod p = 0, 那么 phi(i * p)=phi(i) * p         (我不会证明)

    3.若i mod p ≠0,  那么 phi( i * p )=phi(i) * ( p-1 )   (我不会证明)

     1 const int N = 1e5 + 10;
     2 
     3 int phi[N],prime[N];
     4 int tot;
     5 
     6 void Euler(){
     7     phi[1] = 1;
     8     for (int i=2;i<N;i++){
     9         if (!phi[i]){
    10             phi[i] = i-1;
    11             prime[tot++] = i;
    12         }
    13         for (int j=0;j<tot && 1ll*i*prime[j]<N;j++){
    14             if (i % prime[j]){
    15                 phi[i * prime[j]] = phi[i] * (prime[j] - 1);
    16             }
    17             else{
    18                 phi[i * prime[j]] = phi[i] * prime[j];
    19                 break;
    20             }
    21         }
    22     }
    23 }

    最后说下

    a^b % p  不等价  (a%p)^(b%p) % p

    因为

    a^φ(p) ≡ 1 (mod p)

    所以

    a^b % p  =  (a%p)^(b%φ(p)) % p

    (欧拉函数前提是a和p互质)

    欧拉求余1

    如果p是质数

    直接用这个公式

    欧拉求余2

     我的天哪,我又发现了一个新公式,貌似可以摆脱a和p互质的束缚,让我们来命名为:超欧拉取模进化公式

     

    这是历史性的一刻,妈妈再也不用为a和p不互质而担心了= =

  • 相关阅读:
    20155217 实验四 Android程序设计
    20155217 第十二周课堂测试
    20155217 《Java程序设计》第三次实验报告
    20155217 2016-2017-2 《Java程序设计》第10周学习总结
    20155217 实验二 Java面向对象程序设计 实验报告
    20155217 2016-2017-2 《Java程序设计》第9周学习总结
    20155217 2016-2017-2 《Java程序设计》第8周学习总结
    实验一 Java开发环境的熟悉(Linux+Eclipse)
    Spring阶段性学习总结(一)实现一个简单的HellowWorld
    MySql数据库再学习——使用强化版的自定义连接池连接数据库
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/11358776.html
Copyright © 2011-2022 走看看