集训队专题(2)1003 Matrix Power Series

来源:互联网 发布:2016网络歌曲打包下载 编辑:程序博客网 时间:2024/06/08 02:32

Matrix Power Series

Time Limit : 6000/3000ms (Java/Other)   Memory Limit : 262144/131072K (Java/Other)
Total Submission(s) : 51   Accepted Submission(s) : 26
Problem 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
 

Source
PKU
 

此题是快速幂的一个相当经典的变形运用,求A + A^2 + A^3 + ... + A^k的结果。

这道题两次二分,相当经典。首先我们知道,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<iostream>#include<cstdio>#include<cstring>using namespace std;int n,k,mod;struct Matrix{    int arr[40][40];};Matrix unit,init;Matrix Mul(Matrix a,Matrix b){    Matrix c;    for(int i=0;i<n;i++)        for(int j=0;j<n;j++){            c.arr[i][j]=0;            for(int k=0;k<n;k++)                c.arr[i][j]=(c.arr[i][j]+a.arr[i][k]*b.arr[k][j]%mod)%mod;            c.arr[i][j]%=mod;        }    return c;}Matrix Pow(Matrix a,Matrix b,int x){    while(x){        if(x&1){            b=Mul(b,a);        }        x>>=1;        a=Mul(a,a);    }    return b;}Matrix Add(Matrix a,Matrix b){    Matrix c;    for(int i=0;i<n;i++)        for(int j=0;j<n;j++)            c.arr[i][j]=(a.arr[i][j]+b.arr[i][j])%mod;    return c;}Matrix solve(int x){    if(x==1)        return init;    Matrix res=solve(x/2),cur;    if(x&1){        cur=Pow(init,unit,x/2+1);        res=Add(res,Mul(cur,res));        res=Add(res,cur);    }else{        cur=Pow(init,unit,x/2);        res=Add(res,Mul(cur,res));    }    return res;}int main(){    while(~scanf("%d%d%d",&n,&k,&mod)){        for(int i=0;i<n;i++)            for(int j=0;j<n;j++){                scanf("%d",&init.arr[i][j]);                unit.arr[i][j]=(i==j?1:0);            }        Matrix res=solve(k);        for(int i=0;i<n;i++){            for(int j=0;j<n-1;j++)                printf("%d ",res.arr[i][j]);            printf("%d\n",res.arr[i][n-1]);        }    }    return 0;}


0 0