1. 程式人生 > >POJ 3233 Matrix Power (矩陣快速冪+等比數列求和)

POJ 3233 Matrix Power (矩陣快速冪+等比數列求和)

Matrix Power Series
Time Limit: 3000MS Memory Limit: 131072K
Total Submissions: 23165 Accepted: 9651
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

  • 錯誤總結

今天才知道取模操作多了就會超時以及陣列開大了會RE。。。可怕,乘法裡先是取了兩次模就超時了,取一次 1800MS,嗯,又多了一種TLE和RE的姿勢,還需要努力啊。

  • 其中等比數列的求和其實是二分求解的操作,當K為偶數時,F(A,k)=F(A,k/2)(A^k/2+E),當k為奇數時,F(A,k)=F(A,k/2)(A^(k+1/2)+E)+A^(k+1/2)
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define maxn 1000
#define kuma 35

using namespace std;
typedef long long ll;
ll mod;
ll n;
struct matrix
{
    ll a[kuma][kuma];//陣列開大了居然會RE.....
};
matrix E;
matrix mul(matrix
x,matrix y) { matrix ans=E; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { ans.a[i][j]=0; for(int k=0;k<n;k++) { ans.a[i][j]=(ans.a[i][j]+x.a[i][k]*y.a[k][j])%mod;//取模取多了居然會TLE.... } } } return ans; } matrix add(matrix x,matrix y) { matrix ans=E; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { ans.a[i][j]=(x.a[i][j]+y.a[i][j])%mod; } } return ans; } matrix quickpow(matrix a,ll p) { matrix ans; ans=E; matrix t; t=a; while(p!=0) { if(p&1)ans=mul(ans,t); p>>=1; t=mul(t,t); } return ans; } matrix dos(matrix A,int k) { if(k==1)return A; if(k%2==0) { matrix t=dos(A,k/2); return mul(add(quickpow(A,k/2),E),t); } else { matrix t=dos(A,k/2); matrix q=quickpow(A,(k+1)/2); return add(q,mul(t,add(q,E))); } } void init() { for(int i=0;i<n;i++) E.a[i][i]=1; } int main() { matrix nico; int k; scanf("%I64d%I64d%I64d",&n,&k,&mod); init(); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { scanf("%I64d",&nico.a[i][j]); } } matrix ans=dos(nico,k); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { printf("%I64d ",ans.a[i][j]); } printf("\n"); } return 0; }