快速幂取模(2015.7.29)

取余数有%,即

10%3

可以得到1

但是当数比较大时(比如2999999),计算机可能就无法计算

然而,根据数论的结论,我们可以简化一下。

根据a*b mod c = ( (a mod c) * (b mod c) ) mod c

可以得出 an mod b = (a mod b)n mod b

所以,有 an mod b = (a mod b)n mod b = (a mod b)n/22 mod b = (an/2 mod b)2 mod b = (an/2 mod b)2 mod b

如果用exp_mod(a,n,b)表示an mod b那么就是exp_mod(a,n,b) = exp_mod(a,n/2,b)*exp_mod(a,n/2,b) mod b

那么我们可以不断二分幂,从而减小运算

有几种特殊情况需要考虑

  1. n=0,也即a^n=1,此时模为1%b
  2. n=1,这时二分已经到了终点,可以直接用a%b得到答案
  3. n为奇数,此时n/2会被舍去小数部分,会少乘一个a mod b,可以在补上a mod b

伪代码如下

 

exp_mod(a,n,b){//a^n mod b
    如果n=0
        返回 1 mod b
    如果n=1
        返回 a mod b
    temp=exp_mod(a,n/2,b)//往下二分
    temp=temp^2%b
    如果n是奇数
        temp=temp*a%b
    返回 temp
}

 

代码如下 

typedef long long LL;
LL exp_mod(LL a,LL n,LL b){
    LL t;
    if(n==0) return 1%b;
    if(n==1) return a%b;
    t=exp_mod(a,n/2,b);
    t=t*t%b;
    if((n&1)==1) t=t*a%b;
    return t;
}

 

 附上一道题 COGS-1130. 取余运算

 

posted @ 2015-07-29 20:59  OhYee  阅读(339)  评论(0编辑  收藏  举报