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&10爲偶,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範圍造成錯誤。
資料:
數論之矩陣快速冪