51nod 链接 点击打开链接
codeforces 115C 链接 点击打开链接
本题求放置水管的方式的总数。管道就4个,而且管道的出口都是一边竖直一边水平。
分析后可以发现,水平方向与竖直方向可以分离开来进行考虑。
对于特定的一种放置管道的方式,可以按如下方式进行转化为0,1矩阵:
只考虑竖直: 令向上开口为0,向下为1,则化为0,1的一个矩阵。 上下方向0,1交替出现。
只考虑水平:同样可以得到一个矩阵,有同样的性质。
考虑这两种方式: 放置管道方式 可以 唯一确定 0,1矩阵。
反之, 竖直+水平0,1矩阵 也可以唯一确定 某种放置管道方式。
因此两者是一一对应关系,种数相等。
因此转化为求0,1矩阵的种数。由于0,1矩阵的交替出现的性质,上下01矩阵,某一列出现一个0,1即可确定该列。
因此最终结果只要求未被确定的行数+列数,即可2^(行数+列数)。同时注意可能有矛盾,此时答案为0。
算法实现就是读入初始已给定pattern,统计已确定与未确定的行列即可。
复杂度O(n*m)
#include<cstdio>
#include <cstdlib>
#define maxlen 500001
#define module 1000003
int n, m, figure, myresult = 0;
char ch;
char orientation[maxlen], orientation_row;
inline void GetMyPowerMod(int x, int &y)
{
__int64 result = 1, tmp1 = x;
while (y)
{
if (y & 1) { result = (result * tmp1) % module; }
y >>= 1;
tmp1 = (tmp1 * tmp1) % module;
}
printf("%d", result);
}
inline void exit_pro()
{
printf("0");
exit(0);
}
int main()
{
scanf("%d%d", &n, &m);
getchar();
//cout << "啦啦啦" << flag << endl;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
scanf("%c", &ch);
//printf("%c", ch);
if (ch != '.')
{
if ((figure = ch - '1') > 1)
{
figure = 5 - figure;
}
/* if (f_row) //行
{
//cout << j << '\t' << ((((figure & 2) >> 1) + j) & 1) << '\t' << orientation_row << endl;
if (orientation_row != (((figure & 2) >> 1)^(j&1)))
{
exit_pro();
}
}
else
{
orientation_row = ((((figure & 2) >> 1) ^ (j & 1)));
f_row = true;
}*/
orientation_row |= (1 << ((((figure & 2) >> 1) ^ (j & 1))));
orientation[j] |= (1 << ((figure & 1) ^ (i & 1)));
//cout << f_row << '\t' << orientation[j] << endl;
/* if (f[j]) //行
{
//cout << i << '\t' << (((figure & 1) + i) & 1) <<'\t'<< orientation[j] << endl;
if (orientation[j] != ((figure & 1) ^(i & 1)))
{
exit_pro();
}
}
else
{
// cout << i << '\t' << (((figure & 1) + i) & 1) << '\t' << orientation[j] << endl;
orientation[j] = ((figure & 1) ^ (i & 1));
f[j] = true;
}*/
}
}
getchar();
if (orientation_row>2)
{
exit_pro();
}
myresult += (orientation_row == 0);
//cout << f_row << '\t' << myresult << endl;
//myresult = (myresult << (orientation_row == 0)) % module;
orientation_row = 0;
}
//printf("\n%d", myresult);
//cout << endl<<"kkkkkkkkk"<<flag << endl;
for (int j = 0; j < m; ++j)
{
if (orientation[j] > 2)
{
exit_pro();
}
myresult += (orientation[j] == 0);
//cout << orientation[j] << '\t' << myresult << endl;
//myresult = (myresult << (orientation[j] == 0)) % module;
}
GetMyPowerMod(2, myresult);
//printf("%d\n", myresult);
return 0;
}