洛谷传送门
Codeforces传送门
题意翻译
有一个 n n n 行 m m m 列的棋盘,现在棋盘上的每个位置需要填上 1 1 1 或 − 1 -1 −1 。 其中有 k k k 个位置已经填上了数,而其它的位置则是空的。 定义一个棋盘是好的当且仅当其每一行、每一列都满足所有数的乘积是 − 1 −1 −1 。 你需要计算有多少种填数的方案是好的,答案对 p p p 取模。 0 ≤ k < max { n , m } 0~\leq~k~<~\max\{n,m\} 0 ≤ k < max{n,m}
输入输出格式
输入格式
第一行两个正整数 n , m n, m n,m。
第二行一个非负整数 k k k。
以下 k k k行, 每行三个整数 x , y , v a l x,y,val x,y,val, 表示第 x x x行第 y y y列的格子已经填上了 v a l val val。
最后一行一个正整数 p p p。
输出格式
一行一个正整数, 表示填数的方案数对 p p p的结果。
输入输出样例
输入样例#1:
2 2
0
100
输出样例#1:
2
输入样例#2:
2 2
1
1 1 -1
100
输出样例#2:
1
解题分析
首先, 因为每个格子填成 − 1 -1 −1会对一行一列造成影响, 那么显然如果 n + m n+m n+m为奇数是无解的。
注意到 k < m a x ( n , m ) k<max(n,m) k<max(n,m) , 那么肯定有一行或一列是空的, 我们只要保证其他行或列满足乘积为 − 1 -1 −1, 这一行自然也就有唯一分配方式。所以我们直接考虑每一行的合法分配方式, 实际上就等于 2 t o t − 1 2^{tot-1} 2tot−1( t o t tot tot为该行空位数)。
注意如果某一行/列已经全部填上了 1 1 1,显然就没有解了。
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 1005
#define ll long long
template <class T>
IN void in(T &x)
{
static char c; static bool neg;
x = 0; c = gc;
for (; !isdigit(c); c = gc)
if (c == '-') neg = true;
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
if (neg) neg = false, x = -x;
}
int n, m, k, MOD;
bool vcrs[MX], vcol[MX];
int crs[MX], col[MX], tcrs[MX], tcol[MX];
ll ans = 1;
IN ll fpow(ll base, R int tim)
{
ll ret = 1;
W (tim)
{
if (tim & 1) ret = ret * base % MOD;
base = base * base % MOD, tim >>= 1;
}
return ret;
}
int main(void)
{
int x, y, foo, bar;
in(n), in(m), in(k);
if ((n + m) & 1) return puts("0"), 0;
for (R int i = 1; i <= n; ++i) crs[i] = 1;
for (R int i = 1; i <= m; ++i) col[i] = 1;
for (R int i = 1; i <= k; ++i)
{
in(x), in(y), in(foo);
vcrs[x] |= 1, vcol[y] |= 1;
crs[x] *= foo, col[y] *= foo;
tcrs[x]++, tcol[y]++;
}
in(MOD);
for (R int i = 1; i <= n; ++i) if (tcrs[i] == m && crs[i] == 1) {return puts("0"), 0;}
for (R int i = 1; i <= m; ++i) if (tcol[i] == n && col[i] == 1) {return puts("0"), 0;}
for (R int i = 1; i <= n; ++i) if (!vcrs[i])
{
for (R int j = 1; j <= n; ++j)
{
if (i == j) continue;
if (tcrs[j] >= m - 1) continue;
ans = 1ll * ans * fpow(2, m - tcrs[j] - 1) % MOD;
}
return printf("%lld", ans), 0;
}
for (R int i = 1; i <= m; ++i) if (!vcol[i])
{
for (R int j = 1; j <= m; ++j)
{
if (i == j) continue;
if (tcol[j] >= n - 1) continue;
ans = 1ll * ans * fpow(2, n - tcol[j] - 1) % MOD;
}
return printf("%lld", ans), 0;
}
}