Bootstrap

快速幂运算和矩阵乘法

一、数字快速幂

求x的n次方

package 分治法;

public class 快速幂_初始版 {
	/*
	 * 以最快速度求x的n次方
	 * 时间复杂度:O(log n)
	 */
	public static long quick_Pow(long x,int n) {
		if(n==1)
			return x;
		long temp=x;//x的一次方
		int i=1;   //指数从1开始
		while((i<<1)<n) {
			temp*=temp;//乘方
			i=i<<1; //底数乘方 对应指数翻一倍
			System.out.println(temp+" "+i);
		}
		long ans=quick_Pow(x,n-i);
		ans=ans*temp;
		return ans;
	}

	public static void main(String[] args) {
		System.out.println(quick_Pow(6,12));

	}

}

分析见图片
快速幂_初始版

package 分治法;

public class 快速幂_位运算 {
	static long quick_Pow(long x,int n) {
		if(n==0)
			return 1;
		if(n==1)
			return x;
		long ans=1;
		long pingfang=x; //x的一次方
		while(n!=0) {
			if( (n&1)==1 ) {
				ans*=pingfang;
			}
			pingfang*=pingfang;
			n>>=1; //
		}
		return ans;
	}

	public static void main(String[] args) {
		System.out.println(quick_Pow(2,10));

	}

}

快速幂位运算

二、矩阵快速幂

矩阵快速幂法解斐波那契数列

有一对兔子,从出生后第3个月起,每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子。
假如兔子都不死,求第n个月兔子对数
package 数学类;

import java.util.Scanner;

public class 斐波那契数列_矩阵幂运算 {

	public static void main(String[] args) {
		Scanner reader=new Scanner(System.in);
		int n=reader.nextInt();
		if(n==1||n==2) {
			System.out.println(1);
			//结束程序
			System.exit(0);
		}
		//T矩阵 两行两列
		long[][] T= {
				{0,1},
				{1,1}};	
		//求矩阵T的n-1次方幂
		long[][] ans=matrixPow(T,n-1);
		
		//ans矩阵与[f_1,f_2]矩阵相乘 得到的矩阵的第一个元素就是f_n
		//ans   一行两列 *两行两列得到一行两列
		//不合法运算:matrixMutiply(ans,new long[][] {{1,1}})
		ans=matrixMutiply(new long[][] {{1,1}},ans);
		System.out.println(ans[0][0]);

	}
	//矩阵乘法
	private static long[][] matrixMutiply(long[][] a, long[][] b) {
		//新矩阵的行数和列数分别为a的行数 和b的列数
		final int m=a.length;
		final int n=b[0].length;
		final int q=a[0].length;
		//不满足矩阵乘法的运算
		if(q!=b.length)
			throw new IllegalArgumentException();
		long[][]  ret=new long[m][n];
		for(int i=0;i<m;i++) {
			for(int j=0;j<n;j++) {
				
				for(int k=0;k<q;k++) {
					ret[i][j]+=a[i][k]*b[k][j];
				}
			}
		}
		
		return ret;
	}
	//矩阵幂运算 一定是方阵
	private static long[][] matrixPow(long[][] x, int n) {
		long [][] ans=new long[ x.length ][ x[0].length ];
		//单位矩阵即 对角线为1其余皆为0的矩阵 相当于数字快速幂中的1
		for(int i=0;i<ans.length;i++)
			ans[i][i]=1;
		//平方数
		long pingFang[][]=x; //一次方
		
		while(n!=0) {
			if( (n&1)==1 ) {
				ans=matrixMutiply(ans,pingFang);
			}
			pingFang=matrixMutiply(pingFang, pingFang);
			n>>=1;
		}
		return ans;
	}

}

斐波那契数列矩阵幂

;