因为结合律的存在,所以能进行矩阵快速幂

剑指 Offer 10- I. 斐波那契数列

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

示例 1:
输入:n = 2
输出:1

示例 2:
输入:n = 5
输出:5


提示:

  • 0 <= n <= 100

思路:
矩阵快速幂

Acwing 1303. 斐波那契前 n 项和

大家都知道 Fibonacci 数列吧,f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2
现在问题很简单,输入 n 和 m,求 fn 的前 n 项和 Snmodm。
输入格式
共一行,包含两个整数 n 和 m。
输出格式
输出前 n 项和 Snmodm 的值。
数据范围
1≤n≤2000000000
1≤m≤1000000010
输入样例:
5 1000
输出样例:
12

思路:
矩阵快速幂

  1. /*
  2. Fn = [fn, f(n+1), sn]
  3. F(n+1) = [f(n+1), f(n+2), s(n+1)]
  4. F(n+1) = Fn * [
  5. [0, 1, 0]
  6. [1, 1, 1]
  7. [0, 0, 1]
  8. ]
  9. */
  10. import java.util.*;
  11. public class Main {
  12. static final int N = 3;
  13. static int n, mod;
  14. public static void main(String[] args) {
  15. Scanner sc = new Scanner(System.in);
  16. n = sc.nextInt();
  17. mod = sc.nextInt();
  18. int[][] f1 = {{1, 1, 1}};
  19. int[][] b = {
  20. {0, 1, 0},
  21. {1, 1, 1},
  22. {0, 0, 1}
  23. };
  24. n--;
  25. while (n > 0) {
  26. if ((n & 1) == 1) {
  27. mul(f1, f1, b);
  28. }
  29. n >>= 1;
  30. mul(b, b, b);
  31. }
  32. System.out.println(f1[0][2]);
  33. }
  34. static void mul(int[][] c, int[][] a, int[][] b) {
  35. int x = a.length, y = a[0].length, z = b.length;
  36. int[][] res = new int[x][y];
  37. for (int i = 0; i < x; i++) {
  38. for (int j = 0; j < y; j++) {
  39. long sum = 0;
  40. for (int k = 0; k < z; k++)
  41. sum += 1L * a[i][k] * b[k][j];
  42. res[i][j] = (int)(sum % mod);
  43. }
  44. }
  45. for (int i = 0; i < x; i++)
  46. for (int j = 0; j < y; j++)
  47. c[i][j] = res[i][j];
  48. }
  49. }

AcWing 1217. 垒骰子

思路:
矩阵快速幂

  1. import java.util.*;
  2. public class Main {
  3. static final int MOD = (int)(1e9 + 7);
  4. static int[] map = {3, 4, 5, 0, 1, 2};
  5. static int[][] cof = new int[6][6];
  6. static int[][] f = new int[6][6];
  7. static int n, m;
  8. public static void main(String[] args) {
  9. Scanner sc = new Scanner(System.in);
  10. n = sc.nextInt();
  11. m = sc.nextInt();
  12. Arrays.fill(f[0], 4);
  13. for (int i = 0; i < 6; i++) {
  14. Arrays.fill(cof[i], 4);
  15. }
  16. while (m-- > 0) {
  17. int x = sc.nextInt(), y = sc.nextInt();
  18. x--;
  19. y--;
  20. cof[x][map[y]] = 0;
  21. cof[y][map[x]] = 0;
  22. }
  23. n--;
  24. while (n > 0) {
  25. if ((n & 1) == 1) {
  26. mul(f, f, cof);
  27. }
  28. n >>= 1;
  29. mul(cof, cof, cof);
  30. }
  31. long res = 0;
  32. for (int i = 0; i < 6; i++)
  33. res = (res + f[0][i]) % MOD;
  34. System.out.println(res);
  35. }
  36. static void mul(int[][] c, int[][] a, int[][] b) {
  37. int n = c.length, m = c[0].length, size = b.length;
  38. long[][] res = new long[n][m];
  39. for (int k = 0; k < size; k++) {
  40. for (int i = 0; i < n; i++) {
  41. for (int j = 0; j < m; j++) {
  42. res[i][j] = (res[i][j] + 1L * a[i][k] * b[k][j]) % MOD;
  43. }
  44. }
  45. }
  46. for (int i = 0; i < n; i++)
  47. for (int j = 0; j < m; j++)
  48. c[i][j] = (int)res[i][j];
  49. }
  50. }