思路:矩乘优化DP

提交:3次(用了一个奇怪的东西导致常数过大)

题解:

如果可以走完正向边后又走反向边那就显然了,但是不能走,所以我们要将正反向边分别编号,区分正反向边。

所以这道题的矩阵是以边的编号(边的邻接矩阵),而非点来DP的。

具体地,记录每个边$w_i=(u_i,v_i)$和$w_{i^1}=(v_{i^1},u_{i^1})$,注意这个有向的。

设起点为$s$,终点为$t$,我们的初始矩阵$S$是一根行向量,把所有的$w_i \ and \ u_i==s $设为$1$,表示$s$与$w_i$连通;

然后转移矩阵$a$:若$v_i==u_j \ and \ i!=j \ xor \ 1$ ,即两条边相连,但不是互为正反向边,则在边的邻接矩阵中设为$1$。

然后快速幂,并令$ans=S*a$

最后求解答案时,统计所有$ans$中$w_i \ and \ v_i==t$ 的答案,即为最终的答案。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#define R register int
using namespace std;
//你弱,有什么资格休息
#define ull unsigned long long
#define ll long long
#define pause (for(R i=1;i<=10000000000;++i))
#define In freopen("NOIPAK++.in","r",stdin)
#define Out freopen("out.out","w",stdout)
namespace Fread {
static char B[<<],*S=B,*D=B;
#ifndef JACK
#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
#endif
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
if(ch==EOF) return EOF; do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
} inline bool isempty(const char& ch) {return (ch<=||ch>=);}
inline void gs(char* s) {
register char ch; while(isempty(ch=getchar()));
do *s++=ch; while(!isempty(ch=getchar()));
}
} using Fread::g; using Fread::gs; namespace Luitaryi {
const int N=,M=;
int n,m,p,S,T,cnt=-,x[N],y[N];
int a[N][N],s[][N],ans[][N],anss;
inline void mul(int a[][N],int b[][N]) { R tmp[N][N]; memset(tmp,,sizeof(tmp));
for(R i=;i<=cnt;++i) for(R k=;k<=cnt;++k) for(R j=;j<=cnt;++j)
(tmp[i][j]+=1ll*a[i][k]*b[k][j]%M)%=M;
memcpy(a,tmp,sizeof(tmp));
}
inline void qpow(int p) {
R ret[N][N]; memset(ret,,sizeof(ret));
for(R i=;i<=cnt;++i) ret[i][i]=;
for(;p;p>>=,mul(a,a)) if(p&) mul(ret,a);
memcpy(a,ret,sizeof(ret));
}
inline void main() {
n=g(),m=g(),p=g(),S=g(),T=g();
for(R i=;i<=m;++i) {
R u=g(),v=g();
x[++cnt]=u,y[cnt]=v;
x[++cnt]=v,y[cnt]=u;
} for(R i=;i<=cnt;++i) for(R j=;j<=cnt;++j) if(i!=(j^)&&y[i]==x[j]) a[i][j]+=;
for(R i=;i<=cnt;++i) if(x[i]==S) s[][i]=;
qpow(p-); for(R i=;i<=cnt;++i) for(R j=;j<=cnt;++j) (ans[][j]+=1ll*s[][i]*a[i][j]%M)%=M;
for(R i=;i<=cnt;++i) if(y[i]==T) (anss+=ans[][i])%=M; printf("%d\n",anss);
}
}
signed main() {
Luitaryi::main();
}

2019.07.20

Luogu P2151 [SDOI2009]HH去散步 矩乘加速DP的更多相关文章

  1. 「 洛谷 」P2151 [SDOI2009]HH去散步

    小兔的话 欢迎大家在评论区留言哦~ HH去散步 题目限制 内存限制:125.00MB 时间限制:1.00s 标准输入 标准输出 题目知识点 动态规划 \(dp\) 矩阵 矩阵乘法 矩阵加速 矩阵快速幂 ...

  2. 洛谷P2151 [SDOI2009] HH去散步 [矩阵加速]

    题目传送门 HH去散步 题目描述 HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走 ...

  3. P2151 [SDOI2009]HH去散步

    题目描述 HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因为HH是个喜欢 ...

  4. [bzoj1875] [洛谷P2151] [SDOI2009] HH去散步

    Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又 ...

  5. 洛谷 P2151 [SDOI2009]HH去散步

    题目链接 思路 如果没有不能走上一条边的限制,很显然就是dp. 设f[i][j]表示到达i点走了j步的方案数,移到k点可以表示为f[k][j+1]+=f[i][j]. 如果有限制的话,可以考虑用边表示 ...

  6. Luogu 2151 [SDOI2009]HH去散步

    BZOJ 1875 矩阵乘法加速递推. 如果不要求不能走同一条边,那么直接构造出矩阵快速幂即可,但是不走相同的道路,怎么办? 发现边数$m$也很小,我们直接把$2 * m$开成一个矩阵,相当于记录上一 ...

  7. AC日记——[SDOI2009]HH去散步 洛谷 P2151

    [SDOI2009]HH去散步 思路: 矩阵快速幂递推(类似弗洛伊德): 给大佬跪烂-- 代码: #include <bits/stdc++.h> using namespace std; ...

  8. bzoj 1875: [SDOI2009]HH去散步 -- 矩阵乘法

    1875: [SDOI2009]HH去散步 Time Limit: 20 Sec  Memory Limit: 64 MB Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走, ...

  9. bzoj1875: [SDOI2009]HH去散步

    终于A了...早上按自己以前的写法一直WA.下午换了一种写法就A了qwq #include<cstdio> #include<cstring> #include<iost ...

随机推荐

  1. 将 MathType 公式转换为 Word 自带公式

    以下操作是基于Office 365以及MathType 6.9b平台.有网友留言说第四步没出现「转换为 Office Math」选项,这个我就不清楚了,难道是只有Office 365才支持? 打开Ma ...

  2. STM32与ARM代码执行过程

    内存分配 1.ARM(JZ2440) 启动方式: 1)nor启动 注:1.bootloader烧在norflash的0地址 2.将bootloader从norflash中复制到SDRAM中的链接地址( ...

  3. Nginx 不支持WebSocket TCP

    proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";

  4. Java容器汇总【红黑树需要再次学习】

    1,概述 2,Collection 2.1,Set[接触比较少] 2.1.1 TreeSet 底层由TreeMap实现 基于红黑树实现,支持有序性操作,例如根据一个范围查找元素的操作.但是查找效率不如 ...

  5. sessionId详解

    sessionid是一个会话的key,浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应.服务端在创建了Session的同时,会为该Session生成唯一的se ...

  6. 4、java基础:JDK8接口新特性以及接口和抽象类区别

    在jdk8之前,interface之中可以定义变量和方法,变量必须是public.static.final的,方法必须是public.abstract的.由于这些修饰符都是默认的,所以在JDK8之前, ...

  7. POJ2945(Find the Clones)--字典树,map

    题意:给你n个规定长度的单词,问你其中出现了1次的单词,出现两次的单词...出现n次单词分别有多少个. 当然这题map也能过,但是这里介绍字典树的做法. 首相对于n个单词存入树中,当然建树过程中遇到一 ...

  8. java调用.net的webservice接口

    要调用webservice,首先得有接口,用已经写好的接口地址在myEclipse的目标project中,右键->new web service client-> 选择JAX-WS方式,点 ...

  9. 字符串slice、substring、substr

    1.slice() 可以为负数,如果起始位置为负数,则从字符串最后一位向前找对应位数并且向后取结束位置,如果为正整数则从前往后取起始位置到结束位置. 2.substring() 只能非负整数,截取起始 ...

  10. centos7安装google浏览器

    1. 配置yum源 在目录 /etc/yum.repos.d/ 下新建文件 google-chrome.repo cd /ect/yum.repos.d/ vim google-chrome.repo ...