233 Matrix矩阵快速幂Java

233 Matrix矩阵快速幂Java版

题目背景如下:
在这里插入图片描述

这个题目中重点是构造矩阵,具体的构造过程可参考
233 Matrix HDU - 5015(矩阵快速幂)
这道题目的C++解法很多,这里提供一个自己ac的代码:

public class Solution {
    public static final int mod = 10000007;
    /**
     * @param X: a list of integers
     * @param m: an integer
     * @return: return an integer
     */
    public int calcTheValueOfAnm(int[] X, int m) {
        // write your code here
        int n = X.length;
        if(n==0){
            if(m==0){
                return 0;
            }
            int result=233;
            for(int j=2;j<=m;++j){
                result=(result*10+3)%mod;
            }
            return result;
        }
    	long[][] B =new long[n+2][1];
		B[0][0]=23;
		for(int i =0;i<n;i++){
			B[i+1][0]=X[i];
		}
		B[n+1][0]=3;
		
		long[][] A = new long[n+2][n+2];
		for(int i=0;i<n+1;i++){
			A[i][0]=10;
		}
		for(int i=0;i<n+2;i++){
			A[i][n+1]=1;
		}
		for(int i=1;i<n+1;i++){
			for(int j=1;j<=i;j++){
				A[i][j]=1;
			}
		}
		long[][] res = kuaisumi(A, m);
		long sum=0;
		for(int i=0;i<n+2;i++){
		    System.out.println("sum"+sum);
			sum=(sum+res[n][i]*B[i][0]%mod);
		}
		return (int)sum%mod;
    }
    
    public long[][] mul(long[][] a, long[][] b) {
		int cRowLength = a.length;
		int cColumnLength = b[0].length;
		long[][] c = new long[cRowLength][cColumnLength];
		for (int i = 0; i < cRowLength; i++) {
			for (int j = 0; j < cColumnLength; j++) {
				c[i][j] = 0;
				for (int k = 0; k < a[0].length; k++) {
				    if(a[i][k]*b[k][j]>2147483647){
				        System.out.println("i="+i+"j="+j+"k="+k);
				    }
					c[i][j] += ((a[i][k] * b[k][j]));
					c[i][j]=c[i][j]%mod;
				}
			}
		}
		return c;
	}

	public long[][] kuaisumi(long[][] a, int m) {
		long[][] res = new long[a.length][a[0].length];
		for (int i = 0; i < res.length; i++) {
			for (int j = 0; j < res[0].length; j++) {
				if (i == j) {
					res[i][j] = 1;
				} else {
					res[i][j] = 0;
				}
			}
		}
		while (m != 0) {
			if ((m & 1) == 1) {
				res = mul(res, a);
			}
			m >>= 1;
			a = mul(a, a);
		}
		return res;
	}
    
}

再来谈一谈基础的东西:快速幂。
快速幂的目的就是做到快速求幂,通常的a^b的时间复杂度是O(n),快速幂能做到O(logn)。
首先a^b,将b表示成二进制,比如b10时,10 的二进制是1010,即a ^10 = a ^(1010),可以做到
a ^10 = a ^ (2 ^0) *a ^(2 ^3).结合二进制的操作,& 1 的结果就是取二进制的最末位。还可以判断奇偶x&1
0为偶,x&1==1为奇。>>运算比较单纯,二进制去掉最后一位。
可以得出简单的快速幂模板是这样的

public int fastPow(int a,int b){
    int ans=1,base=a;
    while(b!=0){
        if(b&1!=0)
          ans*=base;
        base*=base;// 如果是矩阵,这里改成矩阵乘法就可以
        b>>=1;
  }
    return ans;
}

如果是矩阵的话,用矩阵乘法代替上面的base*=base;等计算就可以。由于快速幂是指数级增长,需要注意可能超过int范围造成错误。

资料:
数论之矩阵快速幂

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值