矩阵快速幂(入门) 学习笔记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 Matrix
10 {
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         else
63         {
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         else
81         {
82             printf("%d\n", k);
83         }
84     }
85
86     return 0;
87 }
时间: 2024-10-28 01:52:26

矩阵快速幂(入门) 学习笔记hdu1005, hdu1575, hdu1757的相关文章

POJ_Fibonacci POJ_3070(矩阵快速幂入门题,附上自己写的矩阵模板)

Fibonacci Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10521   Accepted: 7477 Description In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For example, the first ten terms of the Fibonacci sequenc

hdu 1575 Tr A(矩阵快速幂入门)

Tr A Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2977    Accepted Submission(s): 2217 Problem Description A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973. Input 数据的第一行是一个T,表示有T组数据. 每组数据的第一行有

HDU 1575 Tr A 【矩阵经典2 矩阵快速幂入门】

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=1575 Tr A Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7572    Accepted Submission(s): 5539 Problem Description A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要

hdu 2604 Queuing(矩阵快速幂乘法)

Problem Description Queues and Priority Queues are data structures which are known to most computer scientists. The Queue occurs often in our daily life. There are many people lined up at the lunch time. Now we define that ‘f’ is short for female and

HDU 2604 Queuing (矩阵快速幂)

HDU 2604 Queuing (矩阵快速幂) ACM 题目地址:HDU 2604 Queuing 题意: n个人排队,f表示女,m表示男,包含子串'fmf'和'fff'的序列为O队列,否则为E队列,有多少个序列为E队列. 分析: 矩阵快速幂入门题. 下面引用巨巨解释: 用f(n)表示n个人满足条件的结果,那么如果最后一个人是m的话,那么前n-1个满足条件即可,就是f(n-1): 如果最后一个是f那么这个还无法推出结果,那么往前再考虑一位:那么后三位可能是:mmf, fmf, mff, fff

UVA10870—Recurrences(简单矩阵快速幂)

题目链接:https://vjudge.net/problem/UVA-10870 题目意思: 给出a1,a2,a3,a4,a5------ad,然后算下面这个递推式子,简单的矩阵快速幂,裸题,但是第一个次遇到了矩阵大小不确定的矩阵快速幂,而且在这道题里面第一次明白了如何构造矩阵.算是矩阵快速幂的学习的一个小里程碑吧. f(n) = a1 *f(n - 1) + a2 *f(n - 2) + a3 *f(n - 3) + - + ad* f(n - d),  n > d.求f(n) 代码: 1

HDU1005 找规律 or 循环点 or 矩阵快速幂

http://acm.hdu.edu.cn/showproblem.php?pid=1005 1.一开始就注意到了n的数据范围 <=100 000 000,但是还是用普通的循环做的,自然TLE了,然后朴素打表,= =运行不了,(怎么可能能把数组开到那么大).再然后就想到了寻找下一个1 1 连续在一起的,那就能开始下一轮循环了. 但是,各种WA--(将数组开大一点,寻找到a[ i ] = a[ i -1 ] ==1 即跳出),这个AC代码将102改成100,150,200都可以,但是108,49

算法笔记--矩阵快速幂

写的不错的博客:http://www.cnblogs.com/yan-boy/archive/2012/11/29/2795294.html 优点:根据数列递推式快速计算数列an的值(当n很大时) 步骤:由数列递推式构造矩阵,然后用矩阵快速幂计算矩阵的幂. 构造矩阵:对于an =x*an-1 +y*an-2 ,可以构造矩阵为: [an ,an-1]=[an-1 ,an-2]*A A=[x 1 y 0]; 矩阵快速幂模板: #include<iostream> #include<cstri

算法学习 - 快速幂和矩阵快速幂(复杂度Olog(n))C++实现

快速幂 快速幂顾名思义,就是快速算某个数的多少次幂.其时间复杂度为 O(log?N), 与朴素的O(N)相比效率有了极大的提高. 快速幂实现原理 快速幂的原理比较好懂,就是说假如我们求的是3^11,其实比较通用的办法就是 for 1:11 a*=3; 时间复杂度为O(n), 那么我们有没有更快的办法呢? 有的~就是下面要说的快速幂. 快速幂就是把指数进行一次log(N)级别的变换.11 = 2^3+2^1+2^0 那么我只需要算3^1和3^2还有3^8这样复杂度就降下来了.算3^1需要一次记为a