【YBTOJ】涂抹果酱

涂抹果酱

题目大意:

在一个 (n imes m) 的矩阵上可以染三个色,同色不相邻。已给出第 (k) 行的方案,求方案数。

正文:

三进制状压,求出来用 (k-1) 的方案乘上 (n-k) 的方案即可。

代码:

const int N = 1e4 + 10, M = 10, M2 = 105;
const int mod = 1e6;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

ll n, m, k;
ll a, p[M] = {1, 3, 9, 27, 81, 243, 729};
ll st[M2];

bool And(int A, int B, bool op = 0)
{
	int i;
	for (i = op; A || B; i++, A /= 3, B /= 3)
		if (A % 3 == B % 3) return 1;
	if (i < m) return 1;
	return 0;
}

void Prework()
{
	for (int i = 0; i < p[m]; i++)
	{
		if(And(i, i / 3, 1)) continue;
		st[++st[0]] = i;
	}
}

ll f[N][M2];
void calc()
{
	for (int i = 1; i <= st[0]; i++)
		if (!And(st[i], a)) 
			f[1][i] = 1;
	for (int i = 2; i <= n; i++)
	{
		for (int j = 1; j <= st[0]; j++)
			for (int k = 1; k <= st[0]; k++)
				if(!And(st[j], st[k]))
					(f[i][j] += f[i - 1][k]) %= mod;
	}
}
ll Solve(int n)
{
	if (n == 0) return 1;
	int ans = 0;
	for (int i = 1; i <= st[0]; i++)
		(ans += f[n][i]) %= mod;
	return ans;
}

int main()
{
	n = Read(), m = Read(), k = Read();
	for (int i = 1; i <= m; i++)
	{
		a = a * 3 + Read() % 3;
		if (a % 3 == a / 3 % 3 && i != 1) {puts("0"); return 0;}
	}
	Prework();
	calc();
	printf ("%lld
", 1ll * Solve(k - 1) * Solve(n - k) % mod);
	return 0;
}
原文地址:https://www.cnblogs.com/GJY-JURUO/p/15037217.html