快速幂形式
public static int f(int a,int b,int c){ int ans =1; int base=a; while(b!=0){ if((b&1)!=0) ans=(ans*base)%c; base=(base*base)%c; } return ans; }
快速乘法幂(优化)
幂转换成乘法,乘法转化成加法
public static int f(int a,int b,int c){ int ans = 0; int base=a; while(b!=0){ if((b&1)!=0) ans=(ans+base)%c; base=(base+base)%c; b>>=1; } return ans; } public static int f1(int a,int b,int c){ int ans =1; int base = a; while(b!=0){ if((b&1)!=0) ans= f(ans, base, c); base=f(base, base, c); b>>=1; } return ans; }
矩阵快速幂
将快速幂里边的1换成一个单位矩阵,然后利用矩阵相乘。
public static long[][] mut(int k,int n,long[][]A){ long [][]res = new long[n][n]; for(int i=0;i<res.length;i++) res[i][i]=1; while(k!=0){ if((k&1)!=0) res=f(res,A); A=f(A,A); k>>=1; } return res; } public static long[][] f(long[][]A,long[][] B){ long res[][]=new long[A.length][B.length]; for(int i=0;i<res.length;i++) for(int j=0;j<res[0].length;j++){ for(int k=0;k<B.length;k++){ res[i][j]+=A[i][k]*B[k][j]; } } return res; }
例题:蓝桥杯 --加强的斐波那契
斐波那契数列大家都非常熟悉。它的定义是:
f(x) = 1 .... (x=1,2)
f(x) = f(x-1) + f(x-2) .... (x> 2)
对于给定的整数 n 和 m,我们希望求出:
f(1) + f(2) + ... + f(n) 的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
import java.util.*; public class Main8 { //基本上是按模板写的 public static long[][] mut(int k,int n,long[][]A){ long [][]res = new long[n][n]; res[1][1]=1; res[1][0]=0; res[0][1]=0; res[0][0]=1; while(k!=0){ if((k&1)!=0) res=f(res,A); A=f(A,A); k>>=1; } return res; } public static long[][] f(long[][]A,long[][] B){ long res[][]=new long[A.length][B.length]; for(int i=0;i<res.length;i++) for(int j=0;j<res[0].length;j++){ for(int k=0;k<B.length;k++){ res[i][j]+=A[i][k]*B[k][j]; } } return res; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); long a[][]=new long [2][2]; a[0][0]=1; a[1][1]=0; a[0][1]=1; a[1][0]=1; long d[][]=mut(n-1,2,a ); System.out.println(d[0][0]%1000000009); } }