题目: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。
下面是我的代码:
#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 33 using 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;