题解  

  这题是一道非常好的插头题,与一般的按格转移的题目不同,由于m很大,要矩阵乘法,这题需要你做一个按列转移的插头DP。

  按列转移多少与按格转移不同,但大体上还是基于连通性进行转移。每一列只有右插头是对下一列的转移有影响的,那么我们只需要记录每一列的右插头的连通情况,用最小表示法表示为当前列的状态。在转移的时候,我们只知道上一列的右插头,即本列的左插头的情况,而上插头还需要自己记一个标记。

  那么我们具体分析:

  1、不存在上插头

    1、同时存在左插头和右插头,不需要修改当前插头,直接把上一列的右插头当做当前列的右插头

    2、只在左插头,即从上一列的某一个连通块转移过来,记录连通块。(左下插头)

    3、只在右插头,即此为一个新的连通块,打上标记,表明这是一个新的连通块。(右下插头)

  2、存在上插头

    1、同时存在左插头和右插头,一个格子里有三个插头,非法状态

    2、都不存在左插头和右插头,不需要修改当前插头,即从上往下。

    3、存在左插头

      1、上插头和左插头同属一个连通块,但不在最终状态(没有右插头)的右下角的格子里出现,非法状态

      2、上插头是左下插头,合并连通块,并删除这两个插头(这个合并比较特殊,因为两个都是已知的连通块,具体画图比较清晰)

      3、上插头是右下插头,合并连通块,删掉当前插头

    4、不存在左插头

      1、上插头是左下插头,合并连通块,删除左下插头

      2、上插头是右下插头,合并为新的连通块

  具体情况还是自己动手画图比较清晰。

  然后就到了矩乘的部分。首先考虑构造矩阵,g[i][j] = 1表示i状态能推到j状态,因此我们只需要枚举这些状态,一个一个判转移就可以了。

  初始的情况下,只存在全空的状态和0和N-1有插头的情况,因此答案就是矩阵快速幂后的ans[1][0],即从初始状态推向终止状态。

程序

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm> using namespace std; #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define DWN(i, a, b) for (int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define mset(a, b) memset(a, b, sizeof(a))
typedef long long LL;
const int MAXD = , HASH = , STATE = , MOD = ;
int n, m, code[MAXD], ch[MAXD];
struct HASHMAP
{
int head[HASH], nxt[STATE], state[STATE], siz;
void clear() { siz = , mset(head, -); }
int push(int x)
{
int pos = x%HASH, i = head[pos];
for (; i != -; i = nxt[i])
if (state[i] == x) return i;
state[siz] = x;
nxt[siz] = head[pos], head[pos] = siz++;
return siz-;
}
}hm;
struct Matrix
{
int mat[][], D;
Matrix operator * (const Matrix &AI) const
{
Matrix ret; ret.D = D;
REP(i, , D)
REP(j, , D)
{
LL sum = ;
REP(k, , D) sum += (LL)mat[i][k]*AI.mat[k][j];
ret.mat[i][j] = sum%MOD;
}
return ret;
}
}rc[], A, B; void decode(int x)
{
DWN(i, n, ) code[i] = x&, x >>= ;
} int encode()
{
int cnt = , ret = ;
mset(ch, -), ch[] = ;
REP(i, , n)
{
if (ch[code[i]] == -) ch[code[i]] = ++cnt;
ret <<= , ret |= ch[code[i]];
}
return ret;
} bool check(int st, int nxt)
{
decode(st);
int up = , k, cnt = ;
REP(i, , n)
{
if (up == )
{
if (!code[i] && !(nxt&(<<(i-)))) return false;
if (code[i] && (nxt&(<<(i-)))) continue ;
if (code[i]) up = code[i];
else up = -;
k = i;
}
else
{
if (code[i] && (nxt&(<<(i-)))) return false;
if (!code[i] && !(nxt&(<<(i-)))) continue ;
if (code[i])
{
if (up == code[i] && !(nxt&(<<(i-))) && (nxt || i != n)) return false;
if (up != -)
{
REP(j, , n) if (code[j] == code[i] && j != i) code[j] = code[k];
code[i] = code[k] = ;
}
else code[k] = code[i], code[i] = ;
}
else
{
if (up != -) code[i] = code[k], code[k] = ;
else code[i] = code[k] = n+(++cnt);
}
up = ;
}
}
if (up) return false;
return true;
} void init()
{
if (rc[n].D != )
{ B = rc[n]; return ; }
mset(rc[n].mat, );
hm.clear(), hm.push();
mset(code, ), code[] = code[n] = , hm.push(encode());
decode(hm.state[]);
for (int i = ; i < hm.siz; ++i)
REP(nxt, , ((<<n)-))
if (check(hm.state[i], nxt))
{
int j = hm.push(encode());
rc[n].mat[i][j] ++;
}
rc[n].D = hm.siz-;
B = rc[n];
} void work()
{
mset(A.mat, ); A.D = B.D;
REP(i, , A.D) A.mat[i][i] = ;
while (m > )
{
if (m&) A = A*B;
B = B*B, m >>= ;
}
if (!A.mat[][]) puts("Impossible");
else printf("%d\n", A.mat[][]);
} int main()
{
REP(i, , ) rc[i].D = ;
while (~scanf("%d %d", &n, &m))
init(), work();
return ;
}

ZOJ 3256 Tour in the Castle 插头DP 矩阵乘法的更多相关文章

  1. 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法

    题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...

  2. 【bzoj3329】Xorequ 数位dp+矩阵乘法

    题目描述 输入 第一行一个正整数,表示数据组数据 ,接下来T行每行一个正整数N 输出 2*T行第2*i-1行表示第i个数据中问题一的解, 第2*i行表示第i个数据中问题二的解, 样例输入 1 1 样例 ...

  3. ZOJ - 3216:Compositions (DP&矩阵乘法&快速幂)

    We consider problems concerning the number of ways in which a number can be written as a sum. If the ...

  4. 【BZOJ-4386】Wycieczki DP + 矩阵乘法

    4386: [POI2015]Wycieczki Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 197  Solved: 49[Submit][Sta ...

  5. Luogu P4643 【模板】动态dp(矩阵乘法,线段树,树链剖分)

    题面 给定一棵 \(n\) 个点的树,点带点权. 有 \(m\) 次操作,每次操作给定 \(x,y\) ,表示修改点 \(x\) 的权值为 \(y\) . 你需要在每次操作之后求出这棵树的最大权独立集 ...

  6. LOJ.6074.[2017山东一轮集训Day6]子序列(DP 矩阵乘法)

    题目链接 参考yww的题解.本来不想写来但是他有一些笔误...而且有些地方不太一样就写篇好了. 不知不觉怎么写了这么多... 另外还是有莫队做法的...(虽然可能卡不过) \(60\)分的\(O(n^ ...

  7. 【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化

    挺好的数位dp……先说一下我个人的做法:经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数 f[i]:所有数 ...

  8. bzoj 3329: Xorequ【数位dp+矩阵乘法】

    注意第一问不取模!!! 因为a+b=a|b+a&b,a^b=a|b-a&b,所以a+b=a^b+2(a&b) x^3x==2x可根据异或的性质以转成x^2x==3x,根据上面的 ...

  9. luogu P4719 【模板】动态 DP 矩阵乘法 + LCT

    方法二:LCT+矩阵乘法 上文中,我们用线段树来维护重链上的各种矩阵转移. 第二种方法是将树链剖分替换为动态树. 我们知道,矩阵乘法 $\begin{bmatrix} F_{u,0} & F_ ...

随机推荐

  1. adb_usb.ini在adb找不到设备时

    不能连接不上adb,如下方法解决,步骤描述不愿意看的话,直接使用本文最下面的批处理命令,方法copy粘贴到新建的bat文件里运行,或者直接粘贴到dos窗口运行. 1. 使用androidsdk目录中的 ...

  2. 大数据系列之kafka监控kafkaoffsetmonitor安装

    1.下载kafkaoffsetmonitor的jar包,可以到github搜索kafkaoffsetmonitor,第一个就是,里面可以下载编译好了的包. KafkaOffsetMonitor-ass ...

  3. Python os模块和sys模块 操作系统的各种接口

    一.os模块 这个模块提供了一个便携式去使用操作系统的相关功能,如果只是想操作路径,请参阅os.path模块. ''' os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 ...

  4. 「caffe编译bug」 undefined reference to `boost::match_results<__gnu_cxx::__normal_iterator<char const*, std::__cxx11

    CXX/LD -o .build_release/tools/test_net.binCXX/LD -o .build_release/tools/convert_annoset.binCXX/LD ...

  5. 报错:Cobbler check 时报错

    报错:[root@test88 ~]# cobbler checkTraceback (most recent call last):  File "/usr/bin/cobbler&quo ...

  6. popstate实现history路由拦截,监听页面返回事件

    1.当活动历史记录条目更改时,将触发popstate事件. 如果被激活的历史记录条目是通过对history.pushState()的调用创建的, 或者受到对history.replaceState() ...

  7. java基础4 函数

    本文知识点(目录): 1.函数的概述    2.函数的格式    3.自定义函数    4.函数的特点    5.函数的应用    6.函数的重载 1.函数的概述 发现不断进行加法运算,为了提高代码的 ...

  8. 转 proc文件

    /proc 是一个伪文件系统, 被用作内核数据结构的接口, 而不仅仅是解释说明/dev/kmem. /proc 里的大多数文件都是只读的, 但也可以通过写一些文件来改变内核变量. 下面对整个 /pro ...

  9. LightOJ 1323 Billiard Balls(找规律(蚂蚁爬木棍))

    题目链接:https://vjudge.net/contest/28079#problem/M 题目大意: 一个边界长为L宽为W的平面同时发射n个台球,运动K秒,台球碰到桌面及两(多)个台球相撞情况如 ...

  10. hexdump related.

    hexdump format strings Tue 13 December 2005 In tips. Ian Wienand More from the "things you'd le ...