学习:数学----欧拉定理与扩展欧拉定理

 

欧拉定理扩展欧拉定理可以解决形如5100000000000000000000等大数幂取模或者求ax mod n=1的大于1的最小x值等一类问题,其中欧拉函数占巨大的重要性,有效的将复杂的大数幂取模问题转化为简单的大数取模和快速幂问题,下面就来介绍一下基本的欧拉定理扩展欧拉定理

 

欧拉函数的定义


 

欧拉函数Φ(n)指1至n以内,与n互质的数的个数

 

当n比较小时,可以通过从前到后遍历的方法计算Φ(n)

对于欧拉函数Φ(n),还有更简单的计算方法。

 

假如n可以通过分解质因子得到n的质因子p1,p2,p3.....pn;

那么

  Φ(n)=n*(1-1/p1)*(1-1/p2)*(1-1/p3)*.....*(1-1/pn)

 

特别的,当n=pr(p为质数)时(p是n的唯一质因子)

  Φ(n)=pr-count(p,2p,3p....pr)=n*(1-1/p)     (证明:由于n分解质因子只有p这一个质因子,故n以内与n不互质的数为p的倍数)

 

当n=p1r1p2r2时(p1和p2是n的所有质因子)

  含有p1的因子为p1,2p1.....p2r2p1r1-1,p2r2p1r1,一共n/p1个;

  含有p2的因子为p2,2p2.....p1r1p2r2-1,p1r1p2r2,一共n/p2个;

  既含有p1又含有p2的因子为p1p2,2p1p2,3p1p2.....p1r1-1p2r2-1,一共n/p1p2个;

  根据容斥定理可知与n不互质数的个数k为n/p1+n/p2-/p1p2;

  那么Φ(n)=n-k=n*(1-1/p1)*(1-1/p2);

 

因此可以推广到n=p1r1p2r2....pnrn

 

 1 ll getDivisor(){
 2     ll sum=p;
 3     int i;
 4     for(i=2;i*i<=p;i++){
 5         if(p%i==0)    sum=(long long)sum*(1-1.0/i);
 6         while(p%i==0)    p=p/i;
 7     }
 8     if(p!=1)    sum=(long long)sum*(1-1.0/p);
 9     return sum;//sum为欧拉函数的值
10 }
求欧拉函数关于p的值

 

 

 

欧拉函数的性质


 

 1)当n为质数时  Φ(n)=n-1

 

2)当m与n互质时  Φ(mn)=Φ(n)*Φ(m)

 

3)当n为质数时  Φ(2n)=Φ(n)

 

例如

  Φ(6)=Φ(3)=2 或Φ(6)=Φ(3)*Φ(2)=2*1=2

 


 

 

 

欧拉定理


 

若n与a互质,则aΦ(n)≡1(mod n)

 

 首先来解释一下  aΦ(n)≡1(mod n)  是什么意思:

  aΦ(n)≡1(mod n) 等价于 aΦ(n) mod n==1 mod n

 

应用:可以解决ax=1(mod n)或ax mod n=1 mod n的最小x的值的问题

 

  由于最小x一定小于等于Φ(n),则令Φ(n)=t*x+b,但由于我们算的x是最小的x,故b等于0,可以得到Φ(n)是x的倍数,因此只要遍历Φ(n)的所有大于logan因数直到找到一个因数k使得ak≡1(mod n)成立,则k就是最小的x。

  

比如让你求4mod 3=1的最小x值:

  4与3本身互质,最小x一定小于等于Φ(3)=2,由于2的大于log43的最小因数为1使得4mod 3=1成立,故x最小取1

 

特别的,当n是质数时,ax=1(mod n)的最小x值为n-1

 


 

 

 

扩展欧拉定理


 

一个公式:ax mod n≡ax mod Φ(n)+Φ(n) mod n  (n与x与a无需满足任何条件)

 

应用:运用扩展欧拉定理可以解决大数幂求模的问题,将利用大数求余很大的x转化为约等于Φ(n)的一个数,然后可以利用快速幂的方法得到结果!

 

如让你求49876543210213657854521 mod 12345的值:

  可以通过分解质因子方法得到Φ(12345)=6576,再利用大数求余求9876543210213657854521 mod 6576=569,再用快速幂求4569+6576 mod 12345=9319

 

 1 #include <iostream>
 2 #include <algorithm> 
 3 #include <string>
 4 #include <sstream>
 5 #define ll1 (ll)1
 6 using namespace std;
 7 typedef long long ll;
 8 stringstream stream;
 9 ll p,divisor,pow1; 
10 string str;
11 int t;
12 ll qSort(){
13     ll x=4,sum=1;
14     while(pow1!=0){
15         if(pow1%2!=0)    sum=sum*x%p;
16         pow1=pow1>>1;
17         x=x*x%p;
18     }
19     return sum;
20 }
21 ll getPow(){
22     stream<<str;
23     ll sum=0;
24     char c;
25     while(stream>>c)
26         sum=(10*sum+c-'0')%divisor;
27     stream.clear();
28     return sum+divisor;
29 }
30 ll getDivisor(){
31     ll sum=p;
32     int i;
33     ll p1=p;
34     for(i=2;i*i<=p1;i++){
35         if(p1%i==0)    sum=ll1*sum*(1-1.0/i);
36         while(p1%i==0)    p1=p1/i;
37     }
38     if(p1!=1)    sum=ll1*sum*(1-1.0/p1);
39     return sum;
40 }
41 int main(){
42     cin>>t;
43     while(t--){
44         cin>>str>>p;
45         divisor=getDivisor();
46         pow1=getPow();
47         cout<<qSort()%p<<endl;
48     }
49     return 0;
50 }
求4的n次方对p取模的代码

 

 

 

总结代码


 

扩展欧拉定理求amod  p代码:

#include <iostream>
#include <string>
#include <sstream>
using namespace std;
long long getOula_function(long long _mod){
    long long i,sum=_mod;
    for(i=2;i*i<=_mod;i++){
        if(!(_mod%i))    sum=(long long)sum*(1.0-1.0/i);
        while(!(_mod%i))    _mod/=i;
    }
    if(_mod!=1)    sum=(long long)sum*(1.0-1.0/_mod);
    return sum;
}
long long getDivisor_function(string _str,long long _oula){
    char c;
    long long sum=0;
    stringstream _stream;
    _stream<<_str;
    while(_stream>>c)    sum=(10*sum+c-'0')%_oula;
    _stream.clear();    
    return sum;
}
long long qPow_function(long long _x,long long _divisor,long long _mod){
    long long sum=1;
    while(_divisor){
        if(_divisor&1)    sum=sum*_x%_mod;
        _divisor=_divisor>>1;
        _x=_x*_x%_mod;
    }
    return sum;
}
long long pow_bigmod(long long _x,string _str,long long _mod){
    long long _oula=getOula_function(_mod);
    long long _divisor=getDivisor_function(_str,_oula)+_oula;
    return qPow_function(_x,_divisor,_mod)%_mod;
}
扩展欧拉公式求大数幂模

使用说明:首先放到代码里面,在main函数中输入pow_bigmod(long long a,string n,long long p),即可返回an mod p的值

 

 欧拉定理求ax≡1(mod n)最小x代码:

#include <iostream>
#include <cmath>
using namespace std;
long long getOula_function(long long _mod){
    long long i,sum=_mod;
      for(i=2;i*i<=_mod;i++){
        if(!(_mod%i))    sum=(long long)sum*(1.0-1.0/i);
        while(!(_mod%i))    _mod/=i;
    }
    if(_mod!=1)    sum=(long long)sum*(1.0-1.0/_mod);
    return sum;
}
long long qPow_function(long long _x,long long _divisor,long long _mod){
    long long sum=1;
    while(_divisor){
        if(_divisor&1)    sum=sum*_x%_mod;
        _divisor=_divisor>>1;
        _x=_x*_x%_mod;
    }
    return sum;
}
long long getMinDiv(long long _base,long long _mod){
    long long _divisor=getOula_function(_mod);
    long long _flag=(long long)(log(_mod)/log(_base));
    long long _top=(long long)sqrt(_divisor);
    for(long long i=_flag+1;i<=_top;i++)
        if(!(_divisor%i) && qPow_function(_base,i,_mod)==1)    return i;
    for(long long i=_top;i>=1;i--)
        if(!(_divisor%i) && qPow_function(_base,_divisor/i,_mod)==1)    return _divisor/i;
}
欧拉定理求a的x次方与n同余的最小x

 使用说明:首先放到代码里面,在main函数中输入getMinDiv(long long base,long long mod),即可返回ax≡1(mod n)最小x的值。

 

 ps:上面两个代码都包含了getOula_function(long long _mod)和qPow_function(long long _x,long long _divisor,long long _mod)函数!


 

 

 

例题


1.牛客练习赛44----D-小y的盒子:https://blog.csdn.net/weixin_43702895/article/details/89672825

 

 

转载于:https://www.cnblogs.com/qiyueliu/p/10793232.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值