Matrix Power Series
Time Limit: 3000MS |
|
Memory Limit: 131072K |
Total Submissions: 7302 |
|
Accepted: 3143 |
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
分析:哎。。。认真线性代数啊
转:
解法一
Let B= A I
0 I
B^(k+1) = A^k I+A+...+A^k
0 I
Accepted2184K250MSG++
解法二
设f[n]=A^1+A^2+....A^n;
当n是偶数,f[n]=f[n/2]+f[n/2]*A^(n/2);
但n是奇数,f[n]=f[n-1]+A^(n);
我的代码(解法一加一点优化)94ms好慢啊:
#include<cstdio> int main() { int n,m,t,i,j,k,p,q,g[31][30][30]= {0},cur[30][30],tem[30][30],a[31][30][30]; scanf("%d%d%d",&n,&t,&m); for(i=0; i<n; ++i) for(j=0; j<n; ++j)scanf("%d",&a[1][i][j]),g[1][i][j]=a[1][i][j]; p=q=1; while((q<<1)<=t) { for(i=0; i<n; ++i) for(j=0; j<n; ++j)cur[i][j]=tem[i][j]=0; for(i=0; i<n; ++i) for(k=0; k<n; ++k) if(a[p][i][k]) for(j=0; j<n; ++j) { cur[i][j]+=a[p][i][k]*g[p][k][j]; tem[i][j]+=a[p][i][k]*a[p][k][j]; if(cur[i][j]>=m)cur[i][j]%=m; if(tem[i][j]>=m)tem[i][j]%=m; } ++p,q<<=1; for(i=0; i<n; ++i) for(j=0; j<n; ++j)g[p][i][j]=(g[p-1][i][j]+cur[i][j])%m,a[p][i][j]=tem[i][j]; } t-=q; for(i=0; i<n; ++i) for(j=0; j<n; ++j)g[0][i][j]=g[p][i][j],a[0][i][j]=a[p][i][j]; while(t>0) { q=p=1; while((q<<1)<=t)++p,q<<=1; t-=q; for(i=0; i<n; ++i) for(j=0; j<n; ++j)cur[i][j]=tem[i][j]=0; for(i=0; i<n; ++i) for(k=0; k<n; ++k) if(a[0][i][k]) for(j=0; j<n; ++j) { cur[i][j]+=a[0][i][k]*g[p][k][j]; tem[i][j]+=a[0][i][k]*a[p][k][j]; if(cur[i][j]>=m)cur[i][j]%=m; if(tem[i][j]>=m)tem[i][j]%=m; } for(i=0; i<n; ++i) for(j=0; j<n; ++j)g[0][i][j]=(g[0][i][j]+cur[i][j])%m,a[0][i][j]=tem[i][j]; } for(i=0; i<n; printf("%d/n",g[0][i++][j])) for(j=0; j<n-1; ++j)printf("%d ",g[0][i][j]); }
代码2,网上找来的,改了一下,79ms,很短很给力~~~:
#include<cstdio> #include<cstring> using namespace std; int i,j,k,n,l,m,r; bool s[32]; struct matrix { int a[30][30]; void pr() { for(i=0; i<n;printf("%d/n",a[i++][j])) for(j=0;j<n-1;++j)printf("%d ",a[i][j]); } matrix& operator+=(const matrix&x) { for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) if(x.a[i][j]) { a[i][j]+=x.a[i][j]; if(a[i][j]>=m)a[i][j]%=m; } return *this; } matrix& operator*=(const matrix&x) { matrix t; int i,j,k; for(i=0; i<n; ++i) for(j=0; j<n; ++j)t.a[i][j]=0; for(i=0; i<n; ++i) for(k=0; k<n; ++k) if(a[i][k]) for(j=0; j<n; ++j) { t.a[i][j]+=a[i][k]*x.a[k][j]; if(t.a[i][j]>=m)t.a[i][j]%=m; } return memcpy(a,t.a,sizeof(a)),*this; } } t,a,unit,ans,exp; int& fun(int &a) { return a; } int main() { for(scanf("%d%d%d",&n,&l,&m),i=0; i<30; ++i)unit.a[i][i]=1; for(i=0; i<n; ++i) for(j=0; j<n; ++j) scanf("%d",a.a[i]+j); for(r=-1;l;l>>=1)s[++r]=l&1; for(ans=exp=a; --r>=0; exp*=exp,s[r]?exp*=a:exp) t=exp,s[r]?ans*=(t*=a)+=unit,ans+=(t=exp)*=a:ans*=t+=unit; ans.pr(); return 0; }