poj3233 又见矩阵,不过是等比吗?
Time Limit: 3000MS | Memory Limit: 131072K | |
Total Submissions: 7775 | Accepted: 3364 |
Description
Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak.
Input
The input contains exactly one test case. The first line of input contains three positive integers n (n ≤ 30), k (k ≤ 109) and m (m < 104). Then follow n lines each containing n nonnegative integers below 32,768, giving A’s elements in row-major order.
Output
Output the elements of S modulo m in the same way as A is given.
Sample Input
2 2 4 0 1 1 1
Sample Output
1 2 2 3
题目大意很明了,初看是像是就等比数列前n项和,但公比是一个矩阵,能用吗?
我不知道,因为如果是类似等比数列前n项和的好像关于矩阵除法比较难写,中间涉及到逆举证神马的,直接忽略
输入的数据第一行分别是n,k,m
代表矩阵的是n×n型,求前k项和,结果的每一项对m取模
然后就是一个n×n的矩阵。
我做这题时用的是类似二分的方法做的,仔细观察可以发现
Sk = A + A2 + A3 + … + Ak
=(1+Ak/2)*(A + A2 + A3 + … + Ak/2 )+{Ak}
=(1+Ak/2)*(Sk/2 )+{Ak}
当k为偶数时不要大括号里面的数
故可以用这方法直接推出答案,中间要记得对数取模,以防超int,还要注意S1=A ;
然后就是写矩阵乘法与加法部分,可直接套模板
参考代码:
1 #include<iostream>
2 #include<cstdlib>
3 #include<cstdio>
4 #include<cstring>
5 #include<algorithm>
6 #include<cmath>
7 using namespace std;
8 int n , m ;
9 struct matrix {//矩阵
10 int a[30][30];
11 void init( )
12 {//初始化
13 int i ;
14 memset ( a, 0 ,sizeof ( a ) ) ;
15 for ( i = 0 ; i < 30 ; i ++ )
16 a[i][i] = 1 ;
17 }
18 };
19 void print ( matrix s )
20 {//打印一个矩阵
21 int i , j ;
22 for ( i = 0 ; i < n ; i ++ )
23 {
24 for ( j = 0 ; j < n ; j ++ )
25 {
26 if ( j )
27 cout<<' ';
28 cout<<s.a[i][j]%m;
29 }
30 cout<<endl;
31 }
32 }
33 matrix matrixadd ( matrix a , matrix b )
34 {//矩阵加法,计算时记得要取模,避免超int
35 int i , j ;
36 matrix c ;
37 for ( i = 0 ; i < n ; i ++ )
38 for ( j = 0 ; j < n ; j ++ )
39 c.a[i][j]=((a.a[i][j]+b.a[i][j])%m);
40 return c ;
41 }
42 matrix matrixmul ( matrix a , matrix b )
43 {//矩阵乘法,计算时记得要取模,避免超int
44 int i , j , k ;
45 matrix c ;
46 for ( i = 0 ; i < n ; i ++ )
47 {
48 for ( j = 0 ; j < n ; j ++ )
49 {
50 c.a[i][j]=0;
51 for ( k = 0 ; k < n ; k ++ )
52 c.a[i][j] +=((a.a[i][k]*b.a[k][j])%m) ;
53 c.a[i][j] %= m ;
54 }
55 }
56 return c ;
57 }
58 matrix mul ( matrix s , int k )
59 {//矩阵的k次方,快速幂
60 matrix ans ;
61 ans .init () ;
62 while ( k >= 1 )
63 {
64 if ( k & 1 )
65 ans = matrixmul ( ans , s ) ;
66 k = k >> 1 ;
67 s = matrixmul ( s , s ) ;
68 }
69 return ans ;
70 }
71 matrix sum ( matrix s , int k )
72 {//举证前k项求和
73 if ( k == 1 )
74 return s ;
75 matrix tmp ;//用来保存答案
76 tmp.init();//初始化
77 tmp = matrixadd ( tmp , mul ( s , k >> 1 ) ); //计算1+A^(k/2)
78 tmp = matrixmul ( tmp , sum ( s , k >> 1 ) ) ; //计算(1+A^(k/2))*(A + A^2 + A^3 + … + A^(k/2) )
79 if ( k&1 )//考虑是否要+A^k
80 tmp = matrixadd ( tmp , mul ( s , k ) ) ;
81 return tmp ;//返回前n项的值
82 }
83
84 int main()
85 {
86 int k ;
87 while ( cin >> n >> k >> m )
88 {
89 int i , j ;
90 matrix s ;
91 for ( i = 0 ; i < n ; i ++ )
92 for ( j = 0 ; j < n ; j ++ )
93 cin >> s.a[i][j] ;
94 s = sum ( s , k ) ;
95 print(s);
96 }
97 return 0;
98 }
作者:ACShiryu
出处:http://www.cnblogs.com/ACShiryu/
若非注明,本博客文章均为原创,版权归作者和博客园共有,欢迎转载,但必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
该文章也同步发布在我的新浪微博中-ACShiryu's weibo,欢迎收听。