首页 > 代码库 > 矩阵快速幂(入门) 学习笔记hdu1005, hdu1575, hdu1757

矩阵快速幂(入门) 学习笔记hdu1005, hdu1575, hdu1757

矩阵快速幂是基于普通的快速幂的一种扩展,如果不知道的快速幂的请参见http://www.cnblogs.com/Howe-Young/p/4097277.html。二进制这个东西太神奇了,好多优秀的算法都跟他有关系,这里所说的矩阵快速幂就是把原来普通快速幂的数换成了矩阵而已,只不过重载了一下运算符*就可以了,也就是矩阵的乘法,  当然也可以写成函数,标题中的这三个题都是关于矩阵快速幂的基础题。拿来练习练习熟悉矩阵快速幂,然后再做比较难点的,其实矩阵快速幂比较难的是构造矩阵。下面还是那题目直接说话:

hdu1575:

题目大意:求一个矩阵k此方之后主对角线上的元素之和对9973取模

这个题是矩阵快速幂的裸题,直接用就行了。下面是代码

 1 #include<iostream> 2 #include <string.h> 3 #include <stdio.h> 4 #include <algorithm> 5  6 using namespace std; 7 const int N = 11; 8 const int mod = 9973; 9 struct Matrix{10     int a[N][N];11 };12 int n;13 Matrix operator * (Matrix t1, Matrix t2)//重载运算符 *  14 {15     Matrix c;16     memset(c.a, 0, sizeof(c.a));17     //矩阵乘法 18     for (int k = 0; k < n; k++)19     {20         for (int i = 0; i < n; i++)21         {22             if (t1.a[i][k] <= 0)23                 continue;24             for (int j = 0; j < n; j++)25             {26                 if (t2.a[k][j] <= 0)27                     continue;28                 c.a[i][j] = (c.a[i][j] + t1.a[i][k] * t2.a[k][j]) % mod;29             }30         }31     }32     return c;33 }34 //重载^运算符 35 Matrix operator ^ (Matrix t, int k)36 {37     Matrix c;38     memset(c.a, 0, sizeof(c.a));39     //初始化矩阵c为单位阵 40     for (int i = 0; i < n; i++)41     {42         c.a[i][i] = 1;43     }44     //这里用到快速幂 45     for (; k; k >>= 1)46     {47         if (k & 1)48             c = c * t;49         t = t * t;50     }51     return c;52 }53 int main()54 {55     int T, k;56     cin >> T;57     while (T--)58     {59         cin >> n >> k;60         Matrix t1, t2;61         for (int i = 0; i < n; i++)62         {63             for (int j = 0; j < n; j++)64                 cin >> t1.a[i][j];65         }66         t2 = t1 ^ k;67         int res = 0;68         for (int i = 0; i < n; i++)69             res = (res + t2.a[i][i]) % mod;70         cout << res << endl;71     }72 73     return 0;74 }

hdu1005:

题目大意:

f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.

给你A, B和n让你求f(n)是多少

这个题就需要稍微构造一下矩阵了

技术分享

这样的话要求F(n)的话,只需要对求出来F(n-1)就行了,对应的F(n-1)要求出F(n-2),所以题目给了F(1)和F(2),所以乘以他前面的系数矩阵就为【F(3), F(2)】T,再接着成系数矩阵就为【F(4),F(3)】T所以要求F(n)只需要对系数矩阵进行n-2次幂就行了,然后最后要求的结果就是矩阵的第一行第一列的结果,代码如下

 1 #include<iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5  6 using namespace std; 7 const int N = 2; 8 const int mod = 7; 9 struct Matrix10 {11     int mat[N][N];12 };13 //矩阵乘法(函数的形式) 14 Matrix Multi(Matrix a, Matrix b)15 {16     Matrix c;17     memset(c.mat, 0, sizeof(c.mat));18     for (int i = 0; i < N; i++)19     {20         for (int j = 0; j < N; j++)21         {22             for (int k = 0; k < N; k++)23                 c.mat[i][j] = (c.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % mod;24         }25     }26     return c;27 }28 //矩阵快速幂 (函数形式) 29 Matrix quickMatrixPower(Matrix a, int k)30 {31     Matrix t;32     memset(t.mat, 0, sizeof(t.mat));33     for (int i = 0; i < N; i++)34         t.mat[i][i] = 1;35     //快速幂 36     while (k)37     {38         if (k & 1)39             t = Multi(t, a);40         a = Multi(a, a);41         k >>= 1;42     }43     return t;44 }45 46 int main()47 {48     long long a, b, n;49     while (cin >> a >> b >> n && (a + b + n))50     {51         Matrix t;52         //初始化系数矩阵 53         t.mat[0][0] = a; 54         t.mat[0][1] = b;55         t.mat[1][0] = 1;56         t.mat[1][1] = 0;57         if (n >= 3)58         {59             t =  quickMatrixPower(t, n - 2);60             printf("%d\n", (t.mat[0][0] + t.mat[0][1]) % mod);61         }62         else63         {64             printf("%lld\n", n);65         }66     }67 68 69     return 0;70 }

hdu1757

题目大意:

If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .

Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.


这个关键还是在于构造矩阵,因为给递推式了,所以矩阵还是比价好构造的,下图是构造的矩阵

技术分享

推到过程类似于1005,不再赘述,代码如下:

 1 #include<iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5  6 using namespace std; 7 const int ori[1][10] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};  8 struct Matrix 9 {10     int str[10][10];11 };12 int m;13 //矩阵乘法 14 Matrix operator * (Matrix a, Matrix b)15 {16     Matrix c;17     memset(c.str, 0, sizeof(c.str));18     for (int i = 0; i < 10; i++)19     {20         for (int j = 0; j < 10; j++)21         {22             for (int k = 0; k < 10; k++)23                 c.str[i][j] = (c.str[i][j] + a.str[i][k] * b.str[k][j]) % m;24        }25     }26     return c;27 }28 //矩阵快速幂 29 Matrix power (Matrix a, int k)30 {31     Matrix c;32     memset(c.str, 0, sizeof(c.str));33     for (int i = 0; i < 10; i++)34         c.str[i][i] = 1;35     while (k)36     {37         if (k & 1)38             c = c * a;39         a = a * a;40         k >>= 1;41     }42     return c;43 }44 //最后一步的矩阵乘法 45 int Multi(Matrix a)46 {47     Matrix c;48     memset(c.str, 0, sizeof(c.str));49     for (int i = 0; i < 1; i++)50     {51         for (int j = 0; j < 10; j++)52         {53             for (int k = 0; k < 10; k++)54             {55                 c.str[i][j] = (c.str[i][j] + ori[i][k] * a.str[k][j]) % m;56             }57         }58     }59     return c.str[0][0] % m;60 }61 int main()62 {63     int k;64     while (cin >> k >> m)65     {66         Matrix t;67         memset(t.str, 0, sizeof(t.str));68         for (int i = 0; i < 10; i++)69         {70             cin >> t.str[i][0];71             for (int j = 0; j < 10; j++)72                 if (i + 1 == j)73                     t.str[i][j] = 1;74         }75         if (k >= 10)76         {77             t = power(t, k - 9);78             printf("%d\n", Multi(t));79         }80         else81         {82             printf("%d\n", k);83         }84     }85 86     return 0;87 }

矩阵快速幂(入门) 学习笔记hdu1005, hdu1575, hdu1757