矩阵乘法 pku 3233 Matrix Power Series hdu 1757 A Simple Math Problem fzu 1683 纪念SlingShot hdu 3306 Another kind of Fibonacc

分析:矩阵相乘O(n^3), 有k次,则复杂度为n^3*k。

使用矩阵技巧,构造:
    B=  |  A  A  |
          |  O  I   |
则B的乘方的结果其右上会是S,其他三个不变。此时化成了矩阵乘方问题,此时可以使用反复平方法,这样复杂度为(2n)^3*logk

#include<stdio.h>
#define nnum 61
int res[nnum][nnum], te[nnum][nnum], n, m;
void mulmatrix(int a[nnum][nnum], int b[nnum][nnum], int mark) {
	int i, j, k, temp[nnum][nnum];
	for (i = 0; i < n; i++) {
		for (j = 0; j < n; j++) {
			temp[i][j] = 0;
			for (k = 0; k < n; k++) {
				temp[i][j] += a[i][k] * b[k][j];
				temp[i][j] %= m;
			}
		}
	}
	if (mark) {
		for (i = 0; i < n; i++) {
			for (j = 0; j < n; j++) {
				te[i][j] = temp[i][j];
			}
		}
	} else {
		for (i = 0; i < n; i++) {
			for (j = 0; j < n; j++) {
				res[i][j] = temp[i][j];
			}
		}
	}
}
void cal(int times) {
	while (times) {
		if (times & 1) {
			mulmatrix(te, res, 1);
		}
		mulmatrix(res, res, 0);
		times >>= 1;
	}
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("t.txt", "r", stdin);
#endif
	int k, i, j, re;
	while (scanf("%d %d %d", &n, &k, &m) != EOF) {
		for (i = 0; i < n; i++) {
			for (j = 0; j < n; j++) {
				scanf("%d", &res[i][j]);
				res[i][j + n] = res[i][j];
			}
		}
		for (i = n; i < n + n; i++) {
			for (j = n; j < n; j++) {
				res[i][j] = 0;
			}
			res[i][i] = 1;
		}
		re = n;
		n = n + n;
		for (i = 0; i < n; i++) {
			for (j = 0; j < n; j++) {
				te[i][j] = 0;
			}
			te[i][i] = 1;
		}
		cal(k);
		for (i = 0; i < re; i++) {
			for (j = re; j < n; j++) {
				printf("%d ", te[i][j]);
			}
			printf("\n");
		}
	}
	return 0;
}
/*
* hdu1757.c
*
* Created on: 2011-9-12
* Author: bjfuwangzhu
*/
//
//#include<stdio.h>
//#define nmax 10
//typedef struct matrix {
// int num[nmax][nmax];
//} matrix;
//int m;
//matrix res, temp;
//matrix matrix_mul(matrix numa, matrix numb) {
// matrix numc;
// int i, j, k;
// for (i = 0; i < nmax; i++) {
// for (j = 0; j < nmax; j++) {
// numc.num[i][j] = 0;
// for (k = 0; k < nmax; k++) {
// numc.num[i][j] += numa.num[i][k] * numb.num[k][j];
// numc.num[i][j] %= m;
// }
// }
// }
// return numc;
//}
//void solve(int k) {
// while (k) {
// if (k & 1) {
// res = matrix_mul(res, temp);
// }
// temp = matrix_mul(temp, temp);
// k >>= 1;
// }
//}
//int main() {
//#ifndef ONLINE_JUDGE
// freopen("data.in", "r", stdin);
//#endif
// int k, i, j, ans;
// while (scanf("%d %d", &k, &m) != EOF) {
// for (i = 0; i < nmax; i++) {
// for (j = 0; j < nmax; j++) {
// temp.num[i][j] = 0;
// res.num[i][j] = 0;
// }
// res.num[i][i] = 1;
// }
// for (i = 0; i < nmax; i++) {
// scanf("%d", &temp.num[0][i]);
// }
// for (i = 0; i < nmax - 1; i++) {
// temp.num[i + 1][i] = 1;
// }
// if (k < nmax) {
// printf("%d\n", k % m);
// continue;
// }
// solve(k - 9);
// for (i = 0, ans = 0; i < nmax; i++) {
// ans += res.num[0][i] * (nmax - 1 - i);
// ans %= m;
// }
// printf("%d\n", ans);
// }
// return 0;
//}
#include<stdio.h>
#define nmax 10
int matrix_res[nmax][nmax], matrix_temp[nmax][nmax];
void matrix_mul(int a[nmax][nmax], int b[nmax][nmax], int m, int mark) {
int temp[nmax][nmax];
int i, j, k;
for (i = 0; i < nmax; i++) {
for (j = 0; j < nmax; j++) {
temp[i][j]
= 0;
for (k = 0; k < nmax; k++) {
temp[i][j]
+= a[i][k] * b[k][j];
temp[i][j]
%= m;
}
}
}
if (mark) {
for (i = 0; i < nmax; i++) {
for (j = 0; j < nmax; j++) {
matrix_res[i][j]
= temp[i][j];
}
}
}
else {
for (i = 0; i < nmax; i++) {
for (j = 0; j < nmax; j++) {
matrix_temp[i][j]
= temp[i][j];
}
}
}
}
void solve(int k, int m) {
if (k < 0) {
return;
}
while (k) {
if (k & 1) {
matrix_mul(matrix_res, matrix_temp, m,
1);
}
matrix_mul(matrix_temp, matrix_temp, m,
0);
k
>>= 1;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen(
"data.in", "r", stdin);
#endif
int k, m, i, j, res;
while (scanf("%d %d", &k, &m) != EOF) {
for (i = 0; i < nmax; i++) {
for (j = 0; j < nmax; j++) {
matrix_temp[i][j]
= 0;
matrix_res[i][j]
= 0;
}
matrix_res[i][i]
= 1;
}
for (i = 0; i < nmax; i++) {
scanf(
"%d", &matrix_temp[0][i]);
}
for (i = 0; i < nmax - 1; i++) {
matrix_temp[i
+ 1][i] = 1;
}
if (k < nmax) {
printf(
"%d\n", k % m);
continue;
}
solve(k
- 9, m);
for (i = 0, res = 0; i < nmax; i++) {
res
= res + matrix_res[0][i] * (nmax - i - 1);
res
%= m;
}
printf(
"%d\n", res);
}
return 0;
}
/*
* fzu1683.c
*
* Created on: 2011-9-12
* Author: bjfuwangzhu
*/

#include
<stdio.h>
#define nnum 2009
#define nmax 4
typedef
struct matrix {
int num[nmax][nmax];
} matrix;
matrix res, temp;
int sum[nmax];
matrix matrix_mul(matrix numa, matrix numb) {
matrix numc;
int i, j, k;
for (i = 0; i < nmax; i++) {
for (j = 0; j < nmax; j++) {
numc.num[i][j]
= 0;
for (k = 0; k < nmax; k++) {
numc.num[i][j]
+= numa.num[i][k] * numb.num[k][j];
numc.num[i][j]
%= nnum;
}
}
}
return numc;
}
void solve(int k) {
while (k) {
if (k & 1) {
res
= matrix_mul(res, temp);
}
temp
= matrix_mul(temp, temp);
k
>>= 1;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen(
"data.in", "r", stdin);
#endif
int m, n, i, j, k, ant;
while (scanf("%d", &m) != EOF) {
for (i = 1; i <= m; i++) {
scanf(
"%d", &n);
for (j = 0; j < nmax; j++) {
for (k = 0; k < nmax; k++) {
temp.num[j][k]
= 0, res.num[j][k] = 0;
}
res.num[j][j]
= 1;
}
temp.num[
0][0] = 1, temp.num[0][1] = 3, temp.num[0][2] = 2, temp.num[0][3] =
7;
temp.num[
1][1] = 3, temp.num[1][2] = 2, temp.num[1][3] = 7;
temp.num[
2][1] = 1, temp.num[3][2] = 1;
sum[
3] = 1, sum[2] = 3, sum[1] = 5, sum[0] = 9;
printf(
"Case %d: ", i);
if (n < nmax - 1) {
for (j = 0, ant = 0; j <= n; j++) {
ant
+= sum[nmax - 1 - j];
ant
%= nnum;
}
printf(
"%d\n", ant);
continue;
}
solve(n
- 2);
for (j = 0, ant = 0; j < nmax; j++) {
ant
+= res.num[0][j] * sum[j];
ant
%= nnum;
}
printf(
"%d\n", ant);
}
}
return 0;
}

 

/*
C语言版
*/
#include
<stdio.h>
#define nmax 4
#define nnum 10007
typedef
struct matrix {
int num[nmax][nmax];
} matrix;
matrix matrix_mul(matrix numa, matrix numb) {
matrix numc;
int i, j, k;
for (i = 0; i < nmax; i++) {
for (j = 0; j < nmax; j++) {
numc.num[i][j]
= 0;
for (k = 0; k < nmax; k++) {
numc.num[i][j]
= (numc.num[i][j]
+ numa.num[i][k] * numb.num[k][j]) % nnum;
}
}
}
return numc;
}
matrix matrix_exp(matrix numc, matrix numa,
int x) {
for (; x; x >>= 1) {
if (x & 1) {
numc
= matrix_mul(numc, numa);
}
numa
= matrix_mul(numa, numa);
}
return numc;
}

int main() {
#ifndef ONLINE_JUDGE
freopen(
"data.in", "r", stdin);
#endif
int i, j, N, X, Y, sum[nmax] = { 2, 1, 1, 1 }, ant;
matrix res, temp;
while (scanf("%d %d %d", &N, &X, &Y) != EOF) {
if (N == 0) {
printf(
"1\n");
continue;
}
if (N == 1) {
printf(
"2\n");
continue;
}
for (i = 0; i < nmax; i++) {
for (j = 0; j < nmax; j++) {
res.num[i][j]
= 0, temp.num[i][j] = 0;
}
res.num[i][i]
= 1;
}
X
%= nnum,Y %= nnum;
temp.num[
0][0] = 1, temp.num[0][1] = X * X % nnum, temp.num[0][2] = Y
* Y % nnum, temp.num[0][3] = 2 * X * Y % nnum;
temp.num[
1][1] = X * X % nnum, temp.num[1][2] = Y * Y % nnum, temp.num[1][3] =
2 * X * Y % nnum;
temp.num[
2][1] = 1, temp.num[3][1] = X, temp.num[3][3] = Y;
res
= matrix_exp(res, temp, (N - 1));
for (i = 0, ant = 0; i < nmax; i++) {
ant
+= res.num[0][i] * sum[i];
ant
%= nnum;
}
printf(
"%d\n", ant);
}
return 0;
}
/*
* hdu3306.cpp
*
* Created on: 2011-9-13
* Author: bjfuwangzhu
*/
/*
C++语言版 重载运算符
*/
#include
<stdio.h>
#define nmax 4
#define nnum 10007
struct matrix {
int num[nmax][nmax];
matrix() {
for (int i = 0; i < nmax; i++) {
for (int j = 0; j < nmax; j++) {
num[i][j]
= 0;
}
}
}
};
matrix
operator*(matrix numa, matrix numb) {
matrix numc;
int i, j, k;
for (i = 0; i < nmax; i++) {
for (j = 0; j < nmax; j++) {
for (k = 0; k < nmax; k++) {
numc.num[i][j]
= (numc.num[i][j]
+ numa.num[i][k] * numb.num[k][j]) % nnum;
}
}
}
return numc;
}
matrix
operator^(matrix numa, int x) {
matrix numc;
int i;
for (i = 0; i < nmax; i++) {
numc.num[i][i]
= 1;
}
for (; x; x >>= 1) {
if (x & 1) {
numc
= numc * numa;
}
numa
= numa * numa;
}
return numc;
}

int main() {
#ifndef ONLINE_JUDGE
freopen(
"data.in", "r", stdin);
#endif
int i, N;
int X, Y, sum[nmax] = { 2, 1, 1, 1 }, ant;
matrix res, temp;
while (scanf("%d %d %d", &N, &X, &Y) != EOF) {
if (N == 0) {
printf(
"1\n");
continue;
}
if (N == 1) {
printf(
"2\n");
continue;
}
X
%= nnum,Y %= nnum;
temp.num[
0][0] = 1, temp.num[0][1] = X * X % nnum, temp.num[0][2] = Y
* Y % nnum, temp.num[0][3] = 2 * X * Y % nnum;
temp.num[
1][1] = X * X % nnum, temp.num[1][2] = Y * Y % nnum, temp.num[1][3] =
2 * X * Y % nnum;
temp.num[
2][1] = 1, temp.num[3][1] = X, temp.num[3][3] = Y;
res
= temp ^ (N - 1);
for (i = 0, ant = 0; i < nmax; i++) {
ant
+= res.num[0][i] * sum[i];
ant
%= nnum;
}
printf(
"%d\n", ant);
}
return 0;
}


 

posted @ 2011-08-15 18:16  qingyezhu  阅读(442)  评论(3编辑  收藏  举报