SRM 554

矩阵连乘

本以为很开心的一道题,矩阵构造太难写了。。

 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;
}


你可能感兴趣的:(topcoder,SRM)