具有结合律,不具有交换律。
一般结合快速幂使用。
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
思路:
构造矩阵
F[n] = [f(n), f(n + 1), s(n)]F[n + 1] = [f(n + 1), f(n + 2), s(n + 1)]F[n + 1] = F[n] * [[0, 1, 0], [1, 1, 1], [0, 0, 1]];A = [[0, 1, 0], [1, 1, 1], [0, 0, 1]]
import java.util.*;public class Main {static int n, m;public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();long[][] A = {{0, 1, 0}, {1, 1, 1}, {0, 0, 1}};long[][] F = {{1, 1, 1}};A = qmi(A, n - 1);F = matrixMul(F, A);System.out.println(F[0][2]);}static long[][] qmi(long[][] b, int c) {int len = b.length;long[][] res = new long[len][len];for (int i = 0; i < len; i++)res[i][i] = 1;while (c > 0) {if ((c & 1) == 1)res = matrixMul(res, b);c >>= 1;b = matrixMul(b, b);}return res;}static long[][] matrixMul(long[][] a, long[][] b) {int row = a.length, col = b[0].length, t = b.length;long[][] res = new long[row][col];for (int k = 0; k < t; k++) {for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {res[i][j] = (res[i][j] + (a[i][k] * b[k][j])) % m;}}}return res;}}
AcWing 1304. 佳佳的斐波那契
佳佳对数学,尤其对数列十分感兴趣。
在研究完 Fibonacci 数列后,他创造出许多稀奇古怪的数列。
例如用 S(n) 表示 Fibonacci 前 nn 项和 modmmodm 的值,即 S(n)=(F1+F2+…+Fn)modm,其中 F1=F2=1,Fi=Fi−1+Fi−2。
可这对佳佳来说还是小菜一碟。
终于,她找到了一个自己解决不了的问题。
用 T(n)=(F1+2F2+3F3+…+nFn)modm 表示 Fibonacci 数列前 n 项变形后的和 modm 的值。
现在佳佳告诉你了一个 n 和 m,请求出 T(n) 的值。
输入格式
共一行,包含两个整数 n 和 m。
输出格式
共一行,输出 T(n) 的值。
数据范围
1≤n,m≤231−1
输入样例:
5 5
输出样例:
1
样例解释
T(5)=(1+2×1+3×2+4×3+5×5)mod5=1
思路:
递推公式 + 矩阵乘法+ 快速幂
// 如何表示 T(n)T(n) = f(1) + 2f(2) + ... + nf(n)nS(n) - T(n) = (n - 1)f(1) + (n - 2)f(2) + ... + f(n - 1)(n + 1)S(n + 1) - T(n + 1) = n(1) + (n - 1)f(2) + ... + 2f(n - 1) + f(n)令P(n) = nS(n) - T(n)p(n + 1) = P(n) + S(n)故可设F(n) = [f(n) f(n+1) S(n) P(n)]F(n + 1) = [f(n+1) f(n+2) S(n+1) P(n+1)] = F(n) *[[0 1 0 0][1 1 1 0][0 0 1 1][0 0 0 1]]
import java.util.*;public class Main {static int n, m;public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();long[][] A = {{0, 1, 0, 0},{1, 1, 1, 0},{0, 0, 1, 1},{0, 0, 0, 1}};long[][] F = {{1, 1, 1, 0}};A = qmi(A, n - 1);F = matrixMul(F, A);System.out.println(((n * F[0][2] - F[0][3]) % m + m) % m);}static long[][] qmi(long[][] a, int b) {int len = a.length;long[][] res = new long[len][len];for (int i = 0; i < len; i++)res[i][i] = 1;while (b > 0) {if ((b & 1) == 1)res = matrixMul(res, a);b >>= 1;a = matrixMul(a, a);}return res;}static long[][] matrixMul(long[][] a, long[][] b) {int row = a.length, col = b[0].length, t = a[0].length;long[][] res = new long[row][col];for (int k = 0; k < t; k++) {for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {res[i][j] = (res[i][j] + a[i][k] * b[k][j]) % m;}}}return res;}}
