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範圍造成錯誤。

資料:
數論之矩陣快速冪

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章