洛谷P2151 [SDOI2009] HH去散步 [矩阵加速]
HH去散步
题目描述
HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。
现在给你学校的地图(假设每条路的长度都是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径
输入输出格式
输入格式:
第一行:五个整数N,M,t,A,B。其中N表示学校里的路口的个数,M表示学校里的 路的条数,t表示HH想要散步的距离,A表示散步的出发点,而B则表示散步的终点。
接下来M行,每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。数据保证Ai != Bi,但 不保证任意两个路口之间至多只有一条路相连接。 路口编号从0到N − 1。 同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。 答案模45989。
输出格式:
一行,表示答案。
输入输出样例
4 5 3 0 0
0 1
0 2
0 3
2 1
3 2
4
说明
对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。
对于100%的数据,N ≤ 50,M ≤ 60,t ≤ 2^30,0 ≤ A,B
分析:
这题的思路其实和[TJOI2017]可乐有些相似。
如果没有那条不会立刻沿着刚刚走来的路走回的限制,那么就直接邻接矩阵搞一波快速幂就行了。但是加了这条限制之后,我们以点作矩阵的元似乎无从下手,那么不如换一下,把边作为矩阵的元。
以边作为矩阵的元,那么所求的结果就变成了与起点相连的所有边到达与终点相连的所有边的方案数。构造矩阵的时候我们就可以先用邻接链表存边,把一条无向边拆成两条有向边,然后在构造矩阵的时候用点来连接两条边,并且判断这两条边是否属于同一条无向边,如果是,在构造矩阵的时候就不用把这条边算上。然后就是矩阵加速转移了。
Code:
//It is made by HolseLee on 11th Sep 2018
//Luogu.org P1224
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; const int mod=;
int n,m,t,sta,ed,head[],cnte,ans;
struct Edge {
int to,nxt;
Edge() {}
Edge(int _x,int _y): to(_x),nxt(_y) {}
}e[];
struct Matrix {
int a[][],n,m; Matrix() {memset(a,,sizeof(a));n=m=;}
Matrix(int b[][]) {memcpy(a,b,sizeof(a));} friend Matrix operator * (const Matrix x,const Matrix y) {
Matrix ret;
ret.n=x.n, ret.m=y.m;
for(int i=; i<=x.n; ++i)
for(int j=; j<=y.m; ++j)
for(int k=; k<=x.m; ++k)
ret.a[i][j]=(ret.a[i][j]+(x.a[i][k]*y.a[k][j])%mod)%mod;
return ret;
}
}M,T; inline int read()
{
char ch=getchar(); int num=; bool flag=false;
while( ch<'' || ch>'' ) {
if( ch=='-' ) flag=true; ch=getchar();
}
while( ch>='' && ch<='' ) {
num=num*+ch-''; ch=getchar();
}
return flag ? -num : num;
} inline void add(int x,int y)
{
e[++cnte]=Edge(y,head[x]);
head[x]=cnte;
} inline int get(int x)
{
return (x&) ? x+ : x-;
} int main()
{
n=read(); m=read(); t=read()-;
sta=read()+, ed=read()+;
memset(head,-,sizeof(head));
int x,y;
for(int i=; i<=m; ++i) {
x=read()+, y=read()+;
add(x,y), add(y,x);
}
for(int j=; j<=cnte; ++j){
x=e[j].to;
for(int i=head[x]; i!=-; i=e[i].nxt) {
if( i==get(j) ) continue;
T.a[j][i]++;
}
}
for(int i=head[sta]; i!=-; i=e[i].nxt) M.a[][i]++;
M.n=, M.m=T.n=T.m=cnte;
while( t ) {
if( t& ) M=M*T;
t>>=, T=T*T;
}
for(int i=head[ed]; i!=-; i=e[i].nxt)
ans=(ans+M.a[][get(i)])%mod;
printf("%d",ans);
return ;
}
洛谷P2151 [SDOI2009] HH去散步 [矩阵加速]的更多相关文章
- [bzoj1875] [洛谷P2151] [SDOI2009] HH去散步
Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又 ...
- 洛谷 P2151 [SDOI2009]HH去散步
题目链接 思路 如果没有不能走上一条边的限制,很显然就是dp. 设f[i][j]表示到达i点走了j步的方案数,移到k点可以表示为f[k][j+1]+=f[i][j]. 如果有限制的话,可以考虑用边表示 ...
- 洛谷2151[SDOI2009]HH去散步(dp+矩阵乘法优化)
一道良好的矩阵乘法优化\(dp\)的题. 首先,一个比较\(naive\)的想法. 我们定义\(dp[i][j]\)表示已经走了\(i\)步,当前在点\(j\)的方案数. 由于题目中限制了不能立即走之 ...
- 「 洛谷 」P2151 [SDOI2009]HH去散步
小兔的话 欢迎大家在评论区留言哦~ HH去散步 题目限制 内存限制:125.00MB 时间限制:1.00s 标准输入 标准输出 题目知识点 动态规划 \(dp\) 矩阵 矩阵乘法 矩阵加速 矩阵快速幂 ...
- bzoj 1875: [SDOI2009]HH去散步 -- 矩阵乘法
1875: [SDOI2009]HH去散步 Time Limit: 20 Sec Memory Limit: 64 MB Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走, ...
- P2151 [SDOI2009]HH去散步
题目描述 HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因为HH是个喜欢 ...
- 【bzoj1875】[SDOI2009]HH去散步 矩阵乘法
题目描述 一张N个点M条边的无向图,从A走到B,要求:每一次不能立刻沿着上一次的边的反方向返回.求方案数. 输入 第一行:五个整数N,M,t,A,B. N表示学校里的路口的个数 M表示学校里的路的条数 ...
- BZOJ1875 [SDOI2009]HH去散步 矩阵
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1875 题意概括 在一个无向图(有重边无自环)中走,不能在经过连续经过某一条边2次. 现在走t步,问 ...
- [luogu2151 SDOI2009] HH去散步 (矩阵快速幂)
传送门 题目描述 HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因为HH ...
随机推荐
- [LeetCode] 23. Merge k Sorted Lists ☆☆
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 解 ...
- Java项目中读取properties文件,以及六种获取路径的方法
下面1-4的内容是网上收集的相关知识,总结来说,就是如下几个知识点: 最常用读取properties文件的方法 InputStream in = getClass().getResourceAsStr ...
- VS Code 配置 C/C++ 环境
写作原因 微软的 VSCode 一直以来为人诟病的一个问题就是对于 C/C++ 工程的编译以及调试支持度有限,配置起来比较复杂,但是 vscode-cpptools 团队经过一段时间的 bug 修复之 ...
- 原生js写Ajax
//原生js写ajax就像打电话 //打电话分下面4步//1.拿出手机//2.拨号//3.说话//4.挺对方说话 //ajax也分下面4步//1.创建ajax对象//2.连接到服务器//3.发送请求( ...
- 带你优雅的使用 icon
前言 本篇文章其实陆陆续续写了快半年,主体部分写好了很久了,但由于种种原因一直没有发布.首先来说说写这篇文章的主要初衷是:在做前端后台项目的时候经常会用到很多 icon 图标,刚开始还好,但随着项目的 ...
- android ViewPager之OnPageChangeListener接口
项目中在使用ViewPager的时候,一般都要在界面滑动的时候做一些事情,android中有个专门的状态回调接口OnPageChangeListener. /** * Callback interfa ...
- pythonif语句和循环语句
1.if语句用法 # if语句用法(缩进相同的成为一个代码块) score=90 if score>=60: print("合格") print("OK" ...
- tar解压与压缩
1.解压 tar -zxvf 压缩文件名 -C 指定的目录 (制定的目录必须存在) 2.压缩 tar -czvf 压缩后的文件名 要压缩的文件夹
- 【Git/GitHub学习笔记】一键更新多个git仓库至远程
因为同时在本地维护几个Github的仓库,每次更新后每个仓库要重复三步提交同步,有点麻烦. 发现可以写.sh文件来实现一键更新. 比如我要更新我的BlogBackup和CodeRepo两个仓库的代码如 ...
- 自动化运维工具SaltStack详细部署【转】
==========================================================================================一.基础介绍==== ...