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 }
时间: 2024-11-07 21:08:20