矩阵快速幂 POJ 3735 Training little cats
1 /*
2 题意:k次操作,g:i猫+1, e:i猫eat,s:swap
3 矩阵快速幂:写个转置矩阵,将k次操作写在第0行,定义A = {1,0, 0, 0...}除了第一个外其他是猫的初始值
4 自己讲太麻烦了,网上有人讲的很清楚,膜拜之
5 详细解释:http://www.cppblog.com/y346491470/articles/157284.html
6 */
7 #include <cstdio>
8 #include <cstring>
9 #include <cmath>
10 #include <algorithm>
11 using namespace std;
12
13 typedef long long ll;
14 const int MAXN = 1e2 + 10;
15 const int INF = 0x3f3f3f3f;
16 struct Mat {
17 ll m[MAXN][MAXN];
18 Mat () {
19 memset (m, 0, sizeof (m));
20 }
21 void init(void) {
22 for (int i=0; i<MAXN; ++i) m[i][i] = 1;
23 }
24 };
25 int n, m, k;
26
27 Mat operator * (Mat &a, Mat &b) {
28 Mat ret;
29 for (int k=0; k<=n; ++k) {
30 for (int i=0; i<=n; ++i) {
31 if (a.m[i][k]) {
32 for (int j=0; j<=n; ++j) {
33 ret.m[i][j] += a.m[i][k] * b.m[k][j];
34 }
35 }
36 }
37 }
38 return ret;
39 }
40
41 Mat operator ^ (Mat x, int n) {
42 Mat ret; ret.init ();
43 while (n) {
44 if (n & 1) ret = ret * x;
45 x = x * x;
46 n >>= 1;
47 }
48 return ret;
49 }
50
51 int main(void) { //POJ 3735 Training little cats
52 while (scanf ("%d%d%d", &n, &m, &k) == 3) {
53 if (!n && !m && !k) break;
54 Mat A, T; A.m[0][0] = 1; T.init ();
55 char op[5]; int p, q;
56 while (k--) {
57 scanf ("%s", op);
58 if (op[0] == 'g') {
59 scanf ("%d", &p); T.m[0][p]++;
60 }
61 else if (op[0] == 'e') {
62 scanf ("%d", &p);
63 for (int i=0; i<=n; ++i) T.m[i][p] = 0;
64 }
65 else {
66 scanf ("%d%d", &p, &q);
67 for (int i=0; i<=n; ++i) swap (T.m[i][p], T.m[i][q]);
68 }
69 }
70 Mat ans = A * (T ^ m);
71 for (int i=1; i<=n; ++i) printf ("%I64d%c", ans.m[0][i], (i==n) ? '\n' : ' ');
72 }
73
74 return 0;
75 }
编译人生,运行世界!