模运算与快速幂算法

部分参考刘扬俊,地址:https://blog.youkuaiyun.com/qq_19782019/article/details/85621386.

下面给出了从最简单的算指数mod1到快速幂算法的递进过程,前面的算法都有其劣势,到最后一种应付基本的大数幂时间上也不成问题了。

模运算:

1.幂模p : (a^b) % p = ((a % p)^b) % p=a% p*a^b-1%p;也就是说每乘一次a对p求一次模,循环b次

(a*b*c)%d=(a%d*b%d*c%d)%d=a%d*b%d*c%d;   a%d和b%d成对的位置可以互换

如a^3%m=a%m*a%m*a%m  

只是要相乘后再取模,就可以先取模再相乘,然后再取模这样算。

注意:(a % p)*(b % p)*(c % p)不可以直接去括号a % p*b % p*c % p   比如(35%3)*(243%3)!=35%3*245%3

2.模p加法:(a + b) % p = (a%p + b%p) % p

3.模p减法:(a - b) % p = (a%p - b%p) % p

4.模p乘法:(a * b) % p = (a % p*b % p) % p= ((a%p)*b)%p

 

    //朴素模幂运算过程   最简单运算
    /*这个算法的时间复杂度体现在for循环中,为O(n).这个算法存在着明显的问题,如果x和n过大,很容易就会溢出。
     * java的普通数字类型是int,4个int的1024相乘(2^40)已经超出了int的表示范围了,2^32,
     * 在乘方时Java发现结果(1000000*1000000)已经超出了int基本数据类型的最大范围(2147483647)输出负数,
     * 原来java在计算时作了默认的类型提升(type promotion),中间结果做为long类型存放,返回结果时目标数据类型int不能 

     * 够容纳下结果,于是根据Java的基础类型的变窄转换(Narrowing primitive conversion)规则,把结果宽于int类型宽度的部       * 分全部丢弃,也就是只取结果的低32位,
     * */
    public static int mod1(int a,int b){//传入底数,指数和模
        if(b==0){
            return 1;
        }else if(b==1){
            return a;
        }else{
            int ans=1;
            for(int i=0;i<b;i++){
                ans*=a;
            }
            return ans;
        }
    }
    // a^b%m的值 一般取模运算  公式 (a%m)^b%m  这种也一样会溢出   可能因为模数比较大  a%m就没效果
    public static int mod2(int a,int b,int m){
        if(b==0){
            return 1;
        }
        else if(b==1){
            return a%m;
        }
        else{
            int ans=1;  
            for(int i=0;i<b;i++){
                ans=ans*(a%m);  //这种方法也可能会发生溢出
            }    
            return ans%m;
        }
        
    }
    //a^b%m =a%m*a^(b-1)%m    边乘边取模  最然很大的数可以求解但是时间很慢
    public static int mod3(int a,int b,int m){
        if(b==0){
            return 1;
        }else if(b==1){
            return a%m;
        }else{
            int ans=1;
            for(int i=1;i<=b;i++){
                ans=ans*a%m;   //防止乘的时候溢出   但是这样的算法复杂度还是太高
            }
            return ans;
        }
    }
    //快速幂乘法  通过扩大底数   缩小指数  同时进行除模运算
    public static long mod4(long a,long b,long m){ 
        if(b==0){
            return 1;
        }else if(b==1){
            return a%m;
        }
        long ans=1; 
        while(b>0){
            if(b%2==0){  //如果指数为偶数
                b/=2;
                a=a*a%m;
            }else{
                b--;
                ans=ans*a%m;
            }
        }
        return ans;
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值