矩阵连乘
本以为很开心的一道题,矩阵构造太难写了。。
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;
}