矩阵连乘
本以为很开心的一道题,矩阵构造太难写了。。
0. 1. 2. 2. 3. 3. 4. 4. 4. 4. 5. 6. ab ab ab aa ab ab ab ab aa ac aa aa cd ba ab bb ca bc ac cb cb bb aa ab这是我人肉的7中情况。。。然后。。。额。。。写了一下午。。。
叉姐好神啊!他貌似先求了4的最小表示,在求了8的最小表示然后。。。
我大概人肉了这7种情况的最小表示,然后枚举了剩下4个的最小表示?反正写的它麻麻都不认识他了。。。
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <cstring> using namespace std; class TheBrickTowerHardDivOne { public: int find(int, int, long long); }; /* 0. 1. 2. 2. 3. 3. 4. 4. 4. 4. 5. 6. ab ab ab aa ab ab ab ab aa ac aa aa cd ba ab bb ca bc ac cb cb bb aa ab 0->0 */ int f[7][4] = { { 0, 1, 2, 3 }, { 0, 1, 1, 0 }, { 0, 1, 0, 1 }, { 0, 1, 2, 0 }, { 0, 1, 0, 2 }, { 0, 0, 0, 0 }, { 0, 0, 0, 1 } }; int id[7][8]; long long a[66][66], t[66][66], tmp[66][66]; int b[4]; bool flag[10]; int ed; long long pmod = 1234567891; void mul(long long a[][66], long long b[][66]) { int i, j, k; memset(tmp, 0, sizeof(tmp)); for (i = 0; i < ed; ++i) { for (j = 0; j < ed; ++j) { for (k = 0; k < ed; ++k) { tmp[i][j] += a[i][k] * b[k][j] % pmod; tmp[i][j] %= pmod; } } } for (i = 0; i < ed; ++i) { for (j = 0; j < ed; ++j) a[i][j] = tmp[i][j]; } } int TheBrickTowerHardDivOne::find(int C, int K, long long H) { int i, j, k, p; ed = 0; for (i = 0; i < 7; ++i) { for (j = 0; j <= K; ++j) { id[i][j] = ed; ed++; } } memset(a, 0, sizeof(a)); for (i = 0; i < 7; ++i) { for (b[0] = 0; b[0] < 8; ++b[0]) { for (b[1] = 0; b[1] < 8; ++b[1]) { for (b[2] = 0; b[2] < 8; ++b[2]) { for (b[3] = 0; b[3] < 8; ++b[3]) { if (f[i][0] >= C) continue; if (f[i][1] >= C) continue; if (f[i][2] >= C) continue; if (f[i][3] >= C) continue; if (b[0] >= C) continue; if (b[1] >= C) continue; if (b[2] >= C) continue; if (b[3] >= C) continue; memset(flag, false, sizeof(flag)); long long v = 1; flag[f[i][0]] = true; flag[f[i][1]] = true; flag[f[i][2]] = true; flag[f[i][3]] = true; if (!flag[b[0]]) v *= max(0, C - b[0]); v %= pmod; for (p = 0; p < b[0]; ++p) { if (!flag[p]) break; } if (p < b[0]) continue; flag[b[0]] = true; if (!flag[b[1]]) v *= max(0, C - b[1]); v %= pmod; for (p = 0; p < b[1]; ++p) { if (!flag[p]) break; } if (p < b[1]) continue; flag[b[1]] = true; if (!flag[b[2]]) v *= max(0, C - b[2]); v %= pmod; for (p = 0; p < b[2]; ++p) { if (!flag[p]) break; } if (p < b[2]) continue; flag[b[2]] = true; if (!flag[b[3]]) v *= max(0, C - b[3]); v %= pmod; for (p = 0; p < b[3]; ++p) { if (!flag[p]) break; } if (p < b[3]) continue; flag[b[3]] = true; int add = 0; if (b[0] == f[i][0]) add++; if (b[1] == f[i][1]) add++; if (b[2] == f[i][2]) add++; if (b[3] == f[i][3]) add++; if (b[0] == b[1]) add++; if (b[1] == b[3]) add++; if (b[3] == b[2]) add++; if (b[2] == b[0]) add++; int typ; if (b[0] == b[1] && b[1] == b[2] && b[2] == b[3]) typ = 5; else if (b[0] == b[1] && b[1] == b[3]) typ = 6; else if (b[1] == b[3] && b[3] == b[2]) typ = 6; else if (b[3] == b[2] && b[2] == b[0]) typ = 6; else if (b[2] == b[0] && b[0] == b[1]) typ = 6; else if (b[0] == b[1] && b[2] == b[3]) typ = 2; else if (b[0] == b[2] && b[1] == b[3]) typ = 2; else if (b[0] == b[3] && b[1] == b[2]) typ = 1; else if (b[0] == b[1] || b[1] == b[3] || b[3] == b[2] || b[2] == b[0]) typ = 4; else if (b[0] == b[3] || b[1] == b[2]) typ = 3; else typ = 0; for (k = 0; k + add <= K; ++k) { a[id[i][k]][id[typ][k + add]] += v; a[id[i][k]][id[typ][k + add]] %= pmod; } } } } } } memset(t, 0, sizeof(t)); for (i = 0; i < ed; ++i) { a[i][ed] = 1; t[i][i] = 1; } t[ed][ed] = 1; a[ed][ed] = 1; ed++; while (H) { if (H & 1) mul(t, a); mul(a, a); H >>= 1; } long long ans = 0; /* 0. 1. 2. 2. 3. 3. 4. 4. 4. 4. 5. 6. ab ab ab aa ab ab ab ab aa ac aa aa cd ba ab bb ca bc ac cb cb bb aa ab */ //0 if (C >= 4) ans += t[id[0][0]][ed - 1] * C * (C - 1) % pmod * (C - 2) * (C - 3) % pmod; //1 if (C >= 2) ans += t[id[1][0]][ed - 1] * C * (C - 1) % pmod; //2 if (C >= 2) if (K >= 2) ans += t[id[2][2]][ed - 1] * C * (C - 1) * 2 % pmod; //3 if (C >= 3) ans += t[id[3][0]][ed - 1] * C * (C - 1) % pmod * (C - 2) * 2 % pmod; //4 if (C >= 3) if (K >= 1) ans += t[id[4][1]][ed - 1] * C * (C - 1) % pmod * (C - 2) * 4 % pmod; //5 if (C >= 1) if (K >= 4) ans += t[id[5][4]][ed - 1] * C; //6 if (C >= 2) if (K >= 2) ans += t[id[6][2]][ed - 1] * C * (C - 1) * 4 % pmod; ans %= pmod; return ans; }