poj3233 Matrix Power Series

来源:互联网 发布:手机恶作剧软件 编辑:程序博客网 时间:2024/04/29 15:31

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 40 11 1

Sample Output

1 22 3


【题意】:给出一个n * n矩阵A和一个正整数k,求 S = A + A2 + A3 + … + Ak

【题解】:以下是matrix67的题解:

这道题两次二分,相当经典。首先我们知道,A^i可以二分求出。然后我们需要对整个题目的数据规模k进行二分。比
如,当k=6时,有:
A + A^2 + A^3 + A^4 + A^5 + A^6 =(A + A^2 + A^3) + A^3*(A + A^2 + A^3)
应用这个式子后,规模k减小了一半。我们二分求出A^3后再递归地计算A + A^2 + A^3,即可得到原问题的答案。




代码:

#include <stdio.h>#include <cstring>int n,m,k;const int N=31;int ans[N][N],A[N][N];void add(int a[][N],int b[][N]) {    for(int i=0; i<n; i++)        for(int j=0; j<n; j++) {            a[i][j]+=b[i][j];            if(a[i][j]>=m) a[i][j]%=m;        }}void mul(int a[][N],int b[][N]) {    int tmp[N][N];    for(int i=0; i<n; i++) {        for(int j=0; j<n; j++) {            tmp[i][j]=0;            for(int k=0; k<n; k++) {                tmp[i][j]+=a[i][k]*b[k][j];                if(tmp[i][j]>=m) tmp[i][j]%=m;            }        }    }    memcpy(a,tmp,sizeof(tmp));}void pow(int a[][N],int b[][N],int x) {    int tmp[N][N];    memcpy(tmp,b,sizeof(int)*N*N);    for(int i=0; i<n; i++)        for(int j=0; j<n; j++) {            if(i==j) a[i][j]=1;            else a[i][j]=0;        }    while(x) {        if(x&1)            mul(a,tmp);        mul(tmp,tmp);        x>>=1;    }}void mat_sum(int a[][N],int b[][N],int x) {    int c[N][N],d[N][N];    if(x==0) {        memset(a,0,sizeof(int)*N*N);        return ;    }    if(x==1) {        memcpy(a,b,sizeof(int)*N*N);        return ;    }    mat_sum(a,b,x>>1);    pow(c,b,x>>1);    memcpy(d,a,sizeof(int)*N*N);    mul(a,c);    add(a,d);    if(x&1) {        mul(c,c);        mul(c,b);        add(a,c);    }}int main() {    while(scanf("%d%d%d",&n,&k,&m)==3) {        for(int i=0; i<n; i++)            for(int j=0; j<n; j++)                scanf("%d",&A[i][j]);        mat_sum(ans,A,k);        for(int i=0; i<n; i++) {            printf("%d",ans[i][0]);            for(int j=1; j<n; j++) {                if(j<n-1) printf(" %d",ans[i][j]);                else printf(" %d\n",ans[i][j]);            }        }    }    return 0;}



原创粉丝点击