Java大数——快速矩阵幂
今天做了一道水题,尽管是水题,但是也没做出来。最后问了一下ChenJ大佬,才慢慢的改对,生无可恋了。。。。
题目描述:
给a,b,c三个数字,求a的b次幂对c取余。
数据范围:多组样例循环输入,每一组输入a,b,c (1<=a,c<=10^9,1<=b<=10^1000000)。
输入:
2 2 2
139123 123124121241452124412124 123121
输出:
0
8984
1、首先我们先定义大数变量
BigInteger a,b,c;
2、然后输入大数
a=input.nextBigInteger();
b=input.nextBigInteger();
c=input.nextBigInteger();
3、之后就是快速矩阵幂算法了
快速矩阵幂就是用二进制来求幂的方法。在说快速矩阵幂之前,我们先看一个例子:A^23 = A^16 * A^4 * A^2 * A。16、4、2、1正好对应的就是23的二进制,即10111。
当我们计算A^2的时候可以通过A*A来获得;当我们计算A^4的时候,可以通过A^2 * A^2获得;同理我们可以通过A^8 * A^8来得到A^16。这就是快速矩阵幂的思想,复杂度从O(n)降到了O(logn)。
运算过程如下:
(用temp记录当前幂的值)当位数==1时,temp*=A,且A=A*A,此时temp=A,A==A^2;
继续 第二位也==1,继续temp*=A,且A=A*A;此时temp=A^3,A==A^4;
继续 第三位也==1,继续temp*=A,且A=A*A;此时temp=A^7,A==A^8;
第四位!=1,继续A=A*A;此时temp=A^7,A==A^16;
继续 第五位==1,继续temp*=A,且A=A*A;此时temp=A^23,A==A^32;
之后退出循环,返回结果temp。
以上只用了5次循环,远远小于23次。
完整代码
import java.math.*;
import java.util.*;
public class Main { public static BigInteger POW (BigInteger a,BigInteger b,BigInteger c)
{ BigInteger ans = BigInteger.valueOf(1);// 大数 1
BigInteger TW=BigInteger.ONE.add(BigInteger.ONE);// 大数 2
while(!b.equals(BigInteger.ZERO))//如果b != 0 进入循环
{
if(b.remainder(TW).equals(BigInteger.ONE)) // 如果该位==1,则ans=ans*a;
ans = (ans.multiply(a)).remainder(c);//
b=b.divide(TW);// 为了下一步计算b二进制的下一位
a = (a.multiply(a)).remainder(c);// a*a 相当于A * A 或者 A^2 * A^2 等等
}
return ans;//返回
} public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
BigInteger a,b,c;
while(input.hasNext()){
a=input.nextBigInteger();
b=input.nextBigInteger();
c=input.nextBigInteger();
System.out.println(POW(a,b,c));
} } }
总结
不做不知道,一做吓一跳,水平太低了,要好好练习了。
欢迎大家指正。