題目:http://poj.org/problem?id=3233
A+A^2+A^3……+A^k
如果k是偶數的話,原式=(I+A^k/2)(A+A^2……A^k/2)。
如果k是奇數的話,原式=(1+A^(k/2+1))(A+A^2……+A^k/2)+A^(k/2+1)。
我是用數組直接實現的,比較麻煩,速度比較慢,1000+ms。
下面是My Code:
#include <stdio.h>int m,n,k;int a[30][30];int ans[30][30],s[30][30],I[30][30];void init(int x[30][30]){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) x[i][j]=0; for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(i==j) x[i][j]=1;}void add(int x[30][30],int y[30][30],int z[30][30]){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) z[i][j]=(x[i][j]+y[i][j])%m;}void multiply(int x[30][30],int y[30][30],int z[30][30]){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) z[i][j]=0; for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) z[i][j]=(z[i][j]+x[i][k]*y[k][j])%m;}void copy(int x[30][30],int y[30][30]){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) y[i][j]=x[i][j];}void quickPow(int a[30][30],int z[30][30],int n){ int x[30][30],y[30][30],b[30][30]; copy(a,b); init(x); init(z); while(n>0) { if(n%2==1) multiply(b,x,z); n=n/2; copy(z,x); multiply(b,b,y); copy(y,b); }}void solve(int a[30][30],int k){ int b[30][30],c[30][30]; if(k==1) { copy(a,ans); copy(a,s); return ; } solve(a,k/2); if(k%2==0) { quickPow(a,b,k/2); add(I,b,c); multiply(c,s,ans); copy(ans,s); } else { quickPow(a,b,k/2+1); add(I,b,c); multiply(c,s,ans); copy(ans,s); add(b,s,ans); copy(ans,s); }}int main(){ //freopen("D:\\a.txt","r",stdin); scanf("%d%d%d",&n,&k,&m); for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&a[i][j]); init(s); init(ans); init(I); solve(a,k); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) printf("%d ",ans[i][j]); printf("\n"); }}
後來看了一些比較快的代碼,200-ms,他們使用結構體實現的,都知道結構體可以作為函數的傳回值,操作簡單,速度相對就快了。
下面是看到的代碼:
原文地址http://www.cnblogs.com/forever4444/archive/2009/05/12/1454736.html
代碼:
#include <iostream>#define MAX 33using namespace std;typedef struct node{ int matirx[MAX][MAX];}Matrix;Matrix a,sa,unit;int n,k,m;void Init(){ int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++) { scanf("%d",&a.matirx[i][j]); a.matirx[i][j]%=m; //初始化要先%m unit.matirx[i][j]=(i==j); //如果i==j那麼矩陣中此值就是1,否則為0,就是主對角線是1的單位矩陣 }}Matrix Add(Matrix a,Matrix b) //矩陣加法{ Matrix c; int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++) { c.matirx[i][j]=a.matirx[i][j]+b.matirx[i][j]; c.matirx[i][j]%=m; //加的時候也要%m } return c;}Matrix Mul(Matrix a,Matrix b) //矩陣乘法{ Matrix c; int i,j,k; for(i=0;i<n;i++) for(j=0;j<n;j++) { c.matirx[i][j]=0; //初始化矩陣c for(k=0;k<n;k++) c.matirx[i][j]+=a.matirx[i][k]*b.matirx[k][j]; c.matirx[i][j]%=m; //計算乘法的時候也要%m } return c;}Matrix Cal(int exp) //矩陣冪{ Matrix p,q; p=a; //p是初始矩陣 q=unit; //q是單位矩陣 while(exp!=1) { if(exp&1) //要求得冪是奇數 { exp--; q=Mul(p,q); } else //要求的冪是偶數 { exp>>=1; //相當於除2 p=Mul(p,p); } } p=Mul(p,q); return p;}Matrix MatrixSum(int k){ if(k==1) //做到最底層就將矩陣a返回就好 return a; Matrix temp,tnow; temp=MatrixSum(k/2); if(k&1) //如果k是奇數 { tnow=Cal(k/2+1); temp=Add(temp,Mul(temp,tnow)); temp=Add(tnow,temp); } else //如果k是偶數 { tnow=Cal(k/2); temp=Add(temp,Mul(temp,tnow)); } return temp;}int main(){ int i,j; while(scanf("%d%d%d",&n,&k,&m)!=EOF) { Init(); sa=MatrixSum(k); for(i=0;i<n;i++) { for(j=0;j<n-1;j++) { printf("%d ",sa.matirx[i][j]%m); } printf("%d\n",sa.matirx[i][n-1]%m); } } return 0;