欧拉函数(二)

此文章纯属原创,内容来源:北大老师的视频教学..

把这个定理的证明弄明白真不容易啊,懂了这个定理,个人觉得欧拉函数就真的不难了...

        定理:若  m,  n  是两个互质的整数,x, y 分别是通过模 m, n 的简化剩余系,则 n*x + m*y 是通过 m*n 的简化剩余系.

       换种写法:x = { x1,x2,x3,x4.... xE(m)}  是mod m 简化剩余系

                           y = { y1,y2,y3,y4..... xE(n)}  是mod n 简化剩余系

                          现在要证明:m*yi + n*xj  { i = 1,2,3,4..E(m) ;j = 1,2,3,...E(n) }  是关于 n*m 的简化剩余系

                          即证明:1:与 n*m 互质

                                          2:不同余

                                          3:关于 n*m 的简化剩余系可以写成m*yi + n*xj  { i = 1,2,3,4..E(m) ;j = 1,2,3,...E(n) }形式

                           证明1:因为(m,n)=1;    { x1,x2,x3,x4.... xE(m)}  是mod m 简化剩余系,

                                         ==>(m,xj)=1;    ==> ( m, n*xj ) =1; ==>

                                         有 带余除法可得 ( a, b ) = ( a, b+a*r ) ==> ( m, m*yi + n*xj ) = 1;      (1)

                                         因为(m, n)=1;    ( n, yi ) = 1;  ==> ( n,m*yi ) = 1; ==>( n,  m * yi + n * xj ) =1;      (2)

                                                                                  由(1)(2)可以得  ( m*n, m*yi + n*xj ) =1;      

                          证明2 :假定 m*yi + n*xj  与 m*yu+n*xv  是mod m*n同余的,那么就要证明 yi==yu  且  xj == xv ;

                                          因为 同余,所以有  m*n  | m * ( yi - yu ) + n * ( xj - xv ) ;

                                                  因为  m|m*n ,n|n*m       ==>m | m * ( yi - yu ) + n * ( xj - xv ) ;   ==> m | n*( xj - xv );  ==>  m | ( xj - xv );

                                                                                               ==>n | m * ( yi - yu ) + n * ( xj - xv ) ;   ==> n | m*( yi - yu );   ==>  n | ( yi - yu );

                                                 又因为     x  = { x1,x2,x3,x4.... xE(m)}  是mod m 简化剩余系

                                                                  y = { y1,y2,y3,y4..... xE(n)}  是mod n 简化剩余系

                                                                 xj - xv mod m 余数一定小于 m 

                                                                 yi - yu mod n 余数一定小于  n

                                                  所以yi == yu  ,  xj == xv ;

                            证明3:任意取一个整数 a ( 0 <= a <= m*n - 1 ), ( m,n ) =1;

                                           则存在 s*m +  n*t =1;  两边同时乘以 a 得a*s*m + a*n*t  =  a;

                                           设 y = s*a,  x = a*t;  则有:m*y + n*x = a; 

                                           那现在证明:任何一个 a 和 m*n 互质的数 即(m*n,a)= 1;   (3)

                                           若  ( n, y ) = 1 并且(m,x)= 1(其中x, y一定是上面x,y简化剩余系中的数据 );

                                           则 和 m * n  互质的数值一定可以写成:m*yi + n*xj  这种形式

                                          那证明(3)(m*n,m*y+n*x)= 1;  ==> ( m,m*y+n*x )  = 1;   ==> ( m, n*x ) = 1;  ==> ( m,x ) = 1;

                                                                                                                  ==>  ( n,m*y+n*x )  = 1;   ==> ( n, m*y ) = 1;  ==> ( n, y ) = 1; 

                                                                                                                                                                                                   证完!!

                       那现在我们来看下:n*m的简化剩余系 m*yi + n*xj 表示

                                                          m*y1+n*x1, m*y2+n*x1, m*y3+n*x1...............m*yE(n)+x1;

                                                          m*y1+n*x2,    ...........              .............                    ..................
                                                          m*y1+n*x3,    .........               .............                       ................

                                                          m*y1+n*x4,     ..........              .............                        ..............

                                                             .....                        ...........             ............                       ....................

                                                             ....                          ..............            ............                     ..............

                                                         m*y1+n*xE(m)          .................        .............              m*yE(n) + n*xE(m);          

                     所以很容易看出来  E( n*m )  =  E( n ) * E( m ) ;  前提是(m,n)= 1;

                     所以就得到了这个非常重要的推论...

 

欧拉函数公式若干:

a = p1^a1*p2^a2*p3^a3*.....*pk^ak;

E(a) = a*( 1-1/p1 ) *( 1-1/p2 )*...*( 1-1/pk );

公式推算就不做了,因为欧拉函数是积性函数,用推论来推就行了...

为了翻译成代码:所以公式变型: E(a) = ( p1-1 )*p1^( a1-1 )    *     ( p2-1 ) * p2^( a2-1 )  *........*  ( pk-1 )*pk^( ak-1 );

我自己写的丑陋代码,勿喷啦..!!

 

#include<iostream>
#include<cmath>
using namespace std;
int euler(int n){
    int sum=1;
    for(int i=2;i*i<=n;i++){
        int a=0;
        if(n%i==0){
            while(n%i==0){
                n /= i;
                a++;
            }
        }
        if(a){
            sum = sum * (i-1) * (int)pow(i*1.0,a-1);
        }   
    }
    if(n>1) sum *= (n-1);    考虑到最后的数可能是素数,所以一定要加上额
    return sum;
}
int main (){
    int n;
    while(cin>>n,n){
        int sum=0;
        sum=euler(n);
        cout<<sum<<endl;
    }   
}

 

 

 

 


 

### 关于欧拉函数的实现与解题思路 #### 一、欧拉函数的核心概念 欧拉函数 \( \phi(n) \) 表示小于等于正整数 \( n \) 中与 \( n \) 互质的数的数量。两个数互质意味着它们的最大公约数为 1。 其定义可以形式化为: \[ \phi(n) = |\{k : 1 \leq k \leq n, gcd(k,n)=1\}| \] 其中,\( gcd(a,b) \) 是指 \( a \) 和 \( b \) 的最大公约数[^1]。 --- #### 欧拉函数的性质 以下是欧拉函数的一些重要性质: 1. 如果 \( p \) 是素数,则 \( \phi(p) = p-1 \),因为所有小于 \( p \) 的自然数都与其互质。 2. 若 \( n = p_1^{k_1}p_2^{k_2}\cdots p_m^{k_m} \) (即 \( n \) 可分解为其唯一素因子乘积),则有: \[ \phi(n) = n \cdot \prod_{i=1}^m \left(1-\frac{1}{p_i}\right) \] 3. 对任意整数 \( m \) 和 \( n \),如果 \( gcd(m,n) = 1 \),那么满足加性关: \[ \phi(mn) = \phi(m)\phi(n) \] 这些性质使得我们可以高效地计算大范围内的欧拉函数值。 --- #### 三、欧拉函数的计算方法 ##### 方法一:基于因数分解的方法 通过上述公式可以直接得出如何利用素因子分解来快速取单个数值对应的欧拉函数值。具体步骤如下所示: 对于给定的一个整数 \( n \),先找出它的所有不同素因子集合 \( P=\{p_1,p_2,\ldots ,p_k\} \),接着按照下面方式逐步累乘得到最终结果: \[ \phi(n) = n \times \prod _{{p\in P}}{\Bigl (}1-{1 \over p}{\Bigr )} \] 此过程的时间复杂度主要取决于寻找素因子的速度,在合理范围内能够接受。 ```python def euler_phi(n): result = n i = 2 while i * i <= n: if n % i == 0: result -= result // i while n % i == 0: n //= i i += 1 if n > 1: result -= result // n return result ``` 以上代码实现了单独查询某个特定数字对应欧拉函数值得功能。 --- #### 四、线性筛法优化批量预处理多个欧拉函数值 当面对大量连续区间上的询问时,采用逐一调用上面提到的独立版效率较低;此时可借助埃氏筛选或者更优美的欧拉筛完成一次性初始化操作后再作答即可达到目的。 下面是使用线性筛的方式预先存储好一定界限以内各位置关联欧拉函数表项的具体做法说明以及相应伪码展示: 初始设定 phi[1]=1 ,其余均置零; 遍历过程中遇到未标记过的当前考察对象x时将其加入候选列表并更新后续可能受影响的位置y=x*p[p_index]处的状态信息直至超出边界为止。 ```python MAXN = int(2e6)+5 phi = list(range(MAXN)) for i in range(2, MAXN): if phi[i]==i: # prime number found for j in range(i, MAXN, i): phi[j]-=(phi[j]//i) print(phi[:20]) #[1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18, 8,...] ``` 这种方法适用于需要频繁访问较小范围的情况下的场景下非常有效率。 --- #### 五、针对题目描述中的解答方案设计 根据所给出的例子来看待输入数据规模较大情形下仍然保持良好性能表现尤为重要因此推荐采取第种全局规划策略即提前准备好必要素材再按需提取答案最为合适不过啦! 样例如下: 假设我们已经完成了前面提及到的大致一百万级别长度数组构建工作之后就可以轻松应对绝大多数常规测试点了。 ```python if __name__=="__main__": import sys input=sys.stdin.read data=input().strip() num=int(data) print(euler_phi(num)) if num<MAXN else None ``` 注意这里为了简化演示忽略了部分细节比如错误捕捉机制等等实际开发当中还是建议补充完善的异常捕获逻辑以便更好地适应各种极端状况哦[^4]! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值