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范围造成错误。
资料:
数论之矩阵快速幂