数学知识-快速幂

一.Euler定理

若a与n互质,那么:

a^{\phi \left ( n \right )} %n=1

证明如下:

设在1~N中与n互质的数为:

x_{1} ,x_{2},x_{3},\cdot \cdot \cdot,x_{\phi \left ( n \right )}

将这组数乘以a,得到:

ax_{1} ,ax_{2},ax_{3},\cdot \cdot \cdot,ax_{\phi \left ( n \right )}

由于an互质,x_{i}也与n互质,那么ax_{i}也一定与n互质,那么ax_{i}%n也一定与n互质,这是因为,假设余数不与n互质,即ax_{i}%n=m,设mn的公约数为phi,且m=p*phi,n=q*phi,设

ax_{i}=yn+m,那么

ax_{i}=y(q*phi)+m=yq*phi+p*phi=(yq+p)*phi

这样,ax_{i}就会和n有公约数phi所以ax_{i}%n的结果一定是某个x_{i},现假设ax_{i}%n=ax_{j}%n,ax_{i}=l*n+t,ax_{j}=m*n+t\left ( l>m,i\neq j \right ),那么a\left ( x_{i}-x_{j} \right )=\left ( l-m \right )*n,但是an是互质的,那么\left (x _{i}-x_{j} \right )一定是n的若干倍,但由于x_{i},x_{j}< n,所以只能x_{i}= x_{j},与前提矛盾,所以ax_{i}n的结果互不相同

因而,ax_{1} ,ax_{2},ax_{3},\cdot \cdot \cdot,ax_{\phi \left ( n \right )}n得到的数,和x_{1} ,x_{2},x_{3},\cdot \cdot \cdot,x_{\phi \left ( n \right )}是同一组数。所以,

ax_{1} ax_{2}ax_{3}\cdot \cdot \cdot ax_{\phi \left ( n \right )}=a^{\phi \left ( n \right )}\left ( x_{1} ,x_{2},x_{3},\cdot \cdot \cdot,x_{\phi \left ( n \right )} \right )(mod n)=x_{1} ,x_{2},\cdot \cdot \cdot,x_{\phi \left ( n \right )}

所以:

a^{\phi \left ( n \right )}(mod n)=1

特别的,当n为质数时,\phi \left ( n \right )=n-1,那么:

a^{n-1}(mod n)=1

这也就是费马定理

二.快速幂

1.算法描述

快速幂是指求解a^{k}%p的问题。基本思路为:

k写成:

k=2^{x_{1}}+2^{x_{2}}+\cdot \cdot \cdot \cdot +2^{x_{n}}

那么:

a^{k}=a^{2^{x_{1}}+2^{x_{2}}+\cdot \cdot \cdot \cdot +2^{x_{n}}}=a^{2^{x_{1}}}a^{2^{x_{2}}}\cdot \cdot \cdot a^{2^{x_{n}}}

而我们把a^{2^{i}}%p的结果记录下来,再相乘即可。

而将k化成2的幂之和的形式很容易,只需要将k写成其二进制的形式即可。所以我们通过k&1和k>>=1把每一次k的最后一位求出来,若该位为1,则相应的求出a^{2^{i}}%p的结果;若该位为0,则更新a的幂以及将k往右移动一位即可。要记住,k在往右移动的同时,a通过平方也不断更新,使得k与a对应,也就是说此时k是第i位,a对应的也是a^{2^{i}}

2.代码实现

k的第i位对应的是a^{2^{i}}%p所以k每移动一位,a平方即可

int power(int a,int b,int p){
    int res=1;
    long long x=a;
    while(b){
        if(b&1) res=res*x%p;
        b>>=1;
        x=x*x%p;
    }
    return res;
}

在实现该函数时,有以下几点需要注意:

1.本来应该是res=\left (res*(x%p) \right )%p,但是其会等价于res=(res*x)%p

2.本来更新为x=x*x,但是x可以到2e9的数量级,那这样你不断平方,是很容易爆掉的,所以在这里我们也模上p,对于整个结果是没有影响的。也正是这样,x会小于p,res会小于p,所以res还是可以用int定义的,所以在数论中,数字会特别大, 为了防止它爆掉,可以考虑在计算一些中间值时模上p

3.为什么不可以直接用a,而要用long long 的x代替a?我是觉得毕竟*和%是同一数量级,有可能到后面p也很大的时候,x尽管会小于p,但它也很大,x定义为int的话,x*x就会爆掉,所以在数论中,也一般将数据类型定义为long long.

完整代码:

#include<iostream>
using namespace std;
int power(int a,int b,int p){
    int res=1;
    long long x=a;
    while(b){
        if(b&1) res=res*x%p;//如果b&1=1,说明这一位是1,需要乘以这个求余的结果
        //需要注意的是,开始是最后一位对应的就是a
        b>>=1;//往右移一位
        x=x*x%p;//更新a的值,平方
    }
    return res;
}
int main(){
    int n;
    cin>>n;
    while(n--){
        int a,b,p;
        scanf("%d%d%d",&a,&b,&p);
        cout<<power(a,b,p)<<endl;
    }
}

3.时间复杂度

这样,去求k的二进制,时间复杂度为O(logk)。

三.快速幂求逆元

1.算法描述:

逆元的定义:若正整数m,b互质,且对于任意b|a的正整数a,若存在整数x,使得

\frac{a}{b}\equiv a*x(mod \, \, m)

则称x为b的模m的逆元,记作:

b^{-1}(mod \, \, m)

将上式转化一下可得:

a\equiv a*b*b^{-1}\left ( mod\, \, m \right )

由于对任意的a成立,那么:

b*b^{-1}\equiv 1\left ( mod\, \, m \right )

此时我们考虑两种情况:

1.b是m的倍数,那么b*b^{-1}\left ( mod\, \, m \right )\equiv 0,此时b不存在逆元。

2.b不是m的倍数,注意到b与m互质,且m为质数的情况下,由费马定理:

b^{m-1}\equiv 1\left ( mod\, \, n \right )

这样:

b^{-1}=b^{m-2}

因而,对于给定的b以及m,在b和m互质且m为质数的前提下,当b是m的倍数时,不存在b的模m的逆元;若b不是m的倍数,存在b的逆元为b^{m-2}

所以每次对于给定的满足b|a的a,要去求它模上m的余数,可以计算a*x模上m的余数,将除法转化为乘法。

2.代码实现

这样,代码就很好实现了,对第二部分快速幂的模板稍作修改即可,即k=m-2,另外在输出时,加上判断b是否时m的语句即可。

具体代码为:

#include<iostream>
using namespace std;
int power(int a,int p){
    int k=p-2;
    long long x=a;
    int res=1;
    while(k){
        if(k&1) res=res*x%p;
        k>>=1;
        x=x*x%p;
    }
    return res;
}
int main(){
    int n;
    cin>>n;
    while(n--){
        int a,p;
        scanf("%d%d",&a,&p);
        if(a%p==0){
            cout<<"impossible"<<endl;
        }
        else{
            cout<<power(a,p)<<endl;
        }
    }
}

感谢AcWing平台。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值