1. 程式人生 > >POJ 3222 Matrix Power Series 【等比矩陣前n項之和(性質 OR 二分?)】

POJ 3222 Matrix Power Series 【等比矩陣前n項之和(性質 OR 二分?)】

Matrix Power Series
Time Limit: 3000MS Memory Limit: 131072K
Total Submissions: 20879 Accepted: 8735

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

題意:求等比矩陣前n項之和對m取餘後的矩陣;

思路:資料量較大,看網上解法有兩種,二分的我寫超時

用陣列代替結構體遞迴函式不好寫也沒寫出來,用等比矩陣的性質寫出一種: 

令 B= [
    [A A]
    [0 I]
]

則 B^k = [
    [A^k     A ... A^k]
    [0                    I ]
]

由A構造出矩陣B之後直接上模板就行,用結構體寫太麻煩,用陣列寫了;

失誤:這道題寫了好久呀,狀態還可以,希望自己不要著急;

AC程式碼:

#include<cstdio>
#include<cstring>

typedef long long LL;
LL ori[77][77],res[77][77];
LL N,mod;

void Mat_mul(LL X[77][77],LL Y[77][77])
{
	LL Z[77][77]; memset(Z,0,sizeof(Z)); 
	LL i=0,j=0,k=0;
	for(i=1;i<=N*2;++i)
	{
		for(k=1;k<=N*2;++k)
		{
			if(X[i][k])
			{
				for(j=1;j<=N*2;++j)
				{
					Z[i][j]+=(X[i][k]*Y[k][j])%mod;
					Z[i][j]%=mod;
				}
			}
		}
	}
	for(i=1;i<=N*2;++i)
	{
		for(j=1;j<=N*2;++j) X[i][j]=Z[i][j]; 
	}
}
void Mat_Q(LL m)
{
	LL i=0;
	memset(res,0,sizeof(res)); 
	for(i=1;i<=2*N;++i) res[i][i]=1;
	while(m)
	{
		if(m&1) Mat_mul(res,ori);
		Mat_mul(ori,ori);
		m>>=1; 
	}
}
int main()
{
	LL K,i,j;
	scanf("%lld %lld %lld",&N,&K,&mod);
	memset(ori,0,sizeof(ori));
	for(i=1;i<=N;++i)
	{
		for(j=1;j<=N;++j)
		{
			scanf("%lld",&ori[i][j]);
			ori[i][j+N]=ori[i][j];
		 } 
	 }
	 for(i=N+1;i<=N*2;++i) ori[i][i]=1;
	 Mat_Q(K);
	 for(i=1;i<=N;++i)
	 {
	 	for(j=N+1;j<=N*2-1;++j)
	 	    printf("%lld ",res[i][j]);
		 printf("%lld\n",res[i][2*N]); 
	 }  
	return 0;
}