快速幂取模问题

快速幂取模:就是求a^bMODc (这就是著名的RSA公钥的加密方法)
因为当AB很大的时候直接求这个问题会在时间和空间上消耗很大

对此类问题我们可以采用以下几种做法:
在这里我随便利用一个例子:HDOJ 的 1420题: 点击打开链接

算法1:
利用公式a*b%c=((a%c)*b)%c(在这里a=b),这样每一步都进行这种处理,这就解决了a^b可能太大存不下的问题,
但这个算法的时间复杂度(O(n))依然没有得到优化,再有些题目可能会超时。
代码如下:
public class P1420{
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		while(n-->0){
			long a=sc.nextLong();
			long b=sc.nextLong();
			long c=sc.nextLong();
			long ans=1;		//记录结果
			if(a>c){
				a=a%c;
			}
			for(int i=1;i<=b;i++){
				ans=ans*a%c;
			}
			System.out.println(ans);
		}
	}
}

算法2:就是利用2分的思想,通过使时间降低为O(log(n))
具体思路为:
我们可以把b的二进制转换为: b = p(n)*2^n  +  p(n-1)*2^(n-1)  +…+   p(1)*2   p(0) 的形式 其中p(n)等于0或者1
a^b =  a^ (p(n)*2^n  p(n-1)*2^(n-1)  +...+  p(1)*2  p(0))
           = a^(p(n)*2^n)  a^(p(n-1)*2^(n-1))  *...*  a^(p(1)*2)  a^p(0)         ———(*)
这里p(n)=0的情况我们不用考虑:因为p(n)=0时 a^p(n)=1;任何数乘以1都等于它本身
化简多项式(*)可以根据秦九韶算法: 点击打开链接
可以得到: a^(2^i) a^(2^(i-1)  * 2) = (  a^(  p(i)  2^(i-1)  )^2
所以我们可以结合前面的得到:a^(2^i)%c = ( (a^(2^(i-1))%c) * a^(2^(i-1)))  %c

代码如下:
package acm;

import java.util.Scanner;

public class P1420 {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		while(n-->0){
			long a=sc.nextLong();
			long b=sc.nextLong();
			long c=sc.nextLong();
			long ans=1;//记录结果
			if(a>c){
				a=a%c;		//如果a>c,就先把a对c取余
			}
			while(b!=0){
				if((b&1)!=0){
					//位运算,若(b&1)=0则说明不用加入计算
					ans=(ans*a)%c;
				}
				b=b/2;//使b的二进制向左移动一位或者可以使用b=b>>1;
				//b=b>>1;
				a=(a*a)%c;
			}
			System.out.println(ans);
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值