【poj3233Matrix Power Series】二分+矩阵乘法或矩阵套矩阵乘法
矩阵乘法啊啊啊233
POJ3233
Matrix Power Series
Time Limit: 3000MS | Memory Limit: 131072K | |
Total Submissions: 27042 | Accepted: 11027 |
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
Source
POJ Monthly--2007.06.03, Huang, Jinsong
这道题思维难度并不大,有两种方法实现
1.二分+矩阵乘法。
因为我们知道对于 x^(2*n) == x^n * ( 1 + x^n)
那么我们可以一直递归下去。
伪代码:
matrix getsum(int x) { if(x==1) return A; if(x&1) return getsum(x-1)*A; else return getsum(x/2) * ( A^(x/2) + 1 ); }2.矩阵套矩阵。 如果我们不看这个A是一个矩阵的话,那么我们看这不就是一个矩阵乘法等比数列求和板题吗?是的,类同那种写法,只是在矩阵里面套的数字也是一个矩阵。 下面只给出二分法的代码:
#include<cstdio> #include<iostream> using namespace std; int n,k,mod; struct arr { int a[35][35]; }; arr A; arr jzjf(arr A,arr B) { arr C; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) C.a[i][j] = 0; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { C.a[i][j] = ( A.a[i][j] + B.a[i][j] )%mod; } } return C; } arr dw; arr jzcf(arr A,arr B) { arr C; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) C.a[i][j] = 0; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { for(int k=1;k<=n;k++) { C.a[i][j] = (C.a[i][j] + A.a[i][k]*B.a[k][j]%mod)%mod; } } } return C; } arr jzksm(int kkk) { arr C; arr D; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(i==j) C.a[i][j] = 1; else C.a[i][j] = 0; } } D=A; for(;kkk;kkk>>=1,D=jzcf(D,D)) if(kkk&1) C=jzcf(C,D); return C; } arr getsum(int x) { if(x==1) return A; if(x&1) return jzjf( jzksm(x) , getsum(x-1) ); else { arr aha = getsum(x/2); return jzjf(jzcf(aha,jzksm(x/2)),aha); } } int main() { scanf("%d%d%d",&n,&k,&mod); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%d",&A.a[i][j]); A.a[i][j] %= mod; } } for(int i=1;i<=n;i++) dw.a[i][i] = 1; arr ans = getsum(k); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { ans.a[i][j]=(ans.a[i][j]%mod+mod)%mod; printf("%d ",ans.a[i][j]%mod); } puts(""); } return 0; }