BZOJ.1875.[SDOI2009]HH去散步(DP 矩阵乘法)
比较容易想到用f[i][j]表示走了i步后到达j点的方案数,但是题目要求不能走上一条走过的边
如果这样表示是不好转移的
可以考虑边,f[i][j]表示走了i步后到达第j条边的方案数,那么有 f[i][j] = ∑f[i-1][k] (边k能直接到达边j)
只要不走反向边,就保证了不会走上一条边了
步数很大,而这个方程显然是可以通过矩阵快速幂加速转移的
求初始边矩阵的t-1次方幂t',然后用系数矩阵(与src相连的边)乘以t',即为走了t条边后的方案数
(这个系数矩阵是为了只保留矩阵中起点是src的路径)
最终答案为所有与des相连的边的dp值
一条边肯定要拆成两条有向边
注意异或运算级比!=还低。。
O((2m)^3logt)=5e7 得卡卡常
为什么自带大常数= =有人帮忙看下吗。。
//1368kb 2900ms
#include <cstdio>
#include <cctype>
#define gc() getchar()
#define mod 45989//真的略快
const int N=150;//,mod=45989;
int n,m,K,src,des,Enum,H[70],nxt[N],to[N];
struct Matrix
{
int A[N][N];
// void Clear() {memset(A,0,sizeof A);}
Matrix operator *(const Matrix &a)const
{
Matrix res;
for(int i=1; i<=m; ++i)
for(int j=1; j<=m; ++j)
{
res.A[i][j]=0;
for(int k=1; k<=m; ++k)
(res.A[i][j]+=A[i][k]*a.A[k][j])%=mod;
}
return res;
// for(int i=1; i<=m; ++i)
// for(int k=1; k<=m; ++k)
// if(A[i][k])//优化技巧 先枚举k 于是可以判是否为0 -> 于是更慢了-- 应该是洛谷评测的问题吧。。
// for(int j=1; j<=m; ++j)
// res.A[i][j]+=A[i][k]*a.A[k][j]%mod,
// res.A[i][j]>=mod ? res.A[i][j]-=mod : 0;
}
}S,tmp;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
Matrix FP(Matrix x,int k)
{
Matrix t=x; --k;
for(; k; k>>=1,x=x*x)
if(k&1) t=t*x;
return t;
}
int main()
{
Enum=1;
n=read(),m=read(),K=read(),src=read(),des=read();
for(int u,v,i=1; i<=m; ++i) u=read(),v=read(),AddEdge(u,v);
m=Enum;
for(int i=H[src]; i; i=nxt[i]) S.A[1][i]=1;//拿1做起点 感觉好玄学啊。。
for(int i=2; i<=m; ++i)
for(int j=H[to[i]]; j; j=nxt[j])//与边i直接相邻的边即边的端点所连的边
if(i!=(j^1)) tmp.A[i][j]=1;//++tmp.A[i][j];//这个是不需要+的,因为已经把每条边都拆了
// if(i^j^1) tmp.A[i][j]=1;
tmp=FP(tmp,K-1);
S=S*tmp;
int res=0;
for(int i=H[des]; i; i=nxt[i]) res+=S.A[1][i^1];//起点到 能到终点的边
printf("%d",res%mod);
return 0;
}
另外如果没有不走前一条边的限制是不是可以倍增Floyd
考试的时候强行看漏句子 然后15min写完以为A了==
#include <cstdio>
#include <cctype>
#include <cstring>
#define gc() getchar()
const int N=30,mod=45989;
int n,m,K,src,des,f[N][N],tmp[N][N],ans[N][N];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
void Mult(int a[N][N],int b[N][N])
{
memset(tmp,0,sizeof tmp);
for(int k=0; k<n; ++k)
for(int i=0; i<n; ++i)
for(int j=0; j<n; ++j)
tmp[i][j]+= a[i][k]*b[k][j]%mod,
tmp[i][j]>=mod ? tmp[i][j]-=mod : 0;
}
//void Print(int a[N][N])
//{
// puts("Debug");
// for(int i=0; i<n; ++i,putchar('\n'))
// for(int j=0; j<n; ++j) printf("%d ",a[i][j]);
//}
int main()
{
n=read(),m=read(),K=read()-1,src=read(),des=read();
for(int u,v,i=1; i<=m; ++i)
u=read(),v=read(),++f[u][v],++f[v][u];
for(int i=0; i<n; ++i)
for(int j=0; j<n; ++j) ans[i][j]=(f[i][j]%=mod);
while(K)
{
if(K&1) Mult(ans,f), memcpy(ans,tmp,sizeof tmp);
K>>=1, Mult(f,f), memcpy(f,tmp,sizeof tmp);
// printf("now K:%d\n",K);
}
printf("%d",ans[src][des]);
return 0;
}
BZOJ.1875.[SDOI2009]HH去散步(DP 矩阵乘法)的更多相关文章
- BZOJ 1875: [SDOI2009]HH去散步( dp + 矩阵快速幂 )
把双向边拆成2条单向边, 用边来转移...然后矩阵乘法+快速幂优化 ------------------------------------------------------------------ ...
- BZOJ 1875: [SDOI2009]HH去散步(矩阵乘法)
首先,题意就把我们引向了矩阵乘法,注意边长m<=60,那么就按边建图,变成一个120个点的图,然后乱搞就行了。 PS:WA了N久改了3次终于A了QAQ CODE: #include<cst ...
- BZOJ 1875 [SDOI2009]HH去散步 ——动态规划 矩阵乘法
发现t非常大,所以大概就是快速幂一类的问题了, 然后根据k^3logn算了算,发现k大约是边数的时候复杂度比较合适. 发现比较麻烦的就是前驱的记录,所以直接把边看做点,不能走反向边,但是可以走重边,然 ...
- 1875. [SDOI2009]HH去散步【矩阵乘法】
Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又 ...
- BZOJ_1875_[SDOI2009]HH去散步_矩阵乘法
BZOJ_1875_[SDOI2009]HH去散步_矩阵乘法 Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时H ...
- bzoj 1875: [SDOI2009]HH去散步 -- 矩阵乘法
1875: [SDOI2009]HH去散步 Time Limit: 20 Sec Memory Limit: 64 MB Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走, ...
- BZOJ-1875 HH去散步 DP+矩阵乘法快速幂
1875: [SDOI2009]HH去散步 Time Limit: 20 Sec Memory Limit: 64 MB Submit: 1196 Solved: 553 [Submit][Statu ...
- bzoj 1875 [SDOI2009]HH去散步(矩乘)
Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因 ...
- [SDOI2009]HH去散步 「矩阵乘法计数」
计数问题也许可以转化为矩阵乘法形式 比如若该题没有不能在一条边上重复走的条件限制,那么直接将邻接矩阵转化为矩阵乘法即可 故 矩阵乘法计数 对于计数问题,若可以将 \(n\) 个点表示成 \(n \ti ...
随机推荐
- Potential Pythonic Pitfalls
Potential Pythonic Pitfalls Monday, 11 May 2015 Table of Contents Not Knowing the Python Version Obs ...
- py-faster-rcnn + opencv3.0.0 + ubuntu16.04配置(CPU模式)
最近开始做行人检测,因此开始接触faster-rcnn,这里贴上配置教程(亲测可行),不过是基于cpu的,蓝瘦... 参考博客:http://www.tuicool.com/articles/nYJr ...
- k64 datasheet学习笔记3---Chip Configuration之System modules
1.前言 本文主要介绍芯片配置的系统模块的内容 2.SIM配置 TODO 3.SMC配置 TODO 4.PMC配置 TODO 5.LOW-LEAKAGE WAKEUP单元配置 TODO 6.MCM配置 ...
- hping网络安全工具的安装及使用
hping是用于生成和解析TCPIP协议数据包的开源工具.创作者是Salvatore Sanfilippo.目前最新版是hping3,支持使用tcl脚本自动化地调用其API.hping是安全审计.防火 ...
- 调试Windows Service
调试Windows Service 使用一般的调试方法调试不了Windows Servers,所以参考了一些调试方法 我服务源码中使用了Timer,注意不能使用工具箱内的Timer,用System.T ...
- Linux 快速删除已输入的命令
从输入模式到命令模式: 按”:“到最后一行,再按ctrl+z 就好了 history 显示命令历史列表 ↑(Ctrl+p) 显示上一条命令 ↓(Ctrl+n) 显示下一条命令 !num 执行命令历史列 ...
- Fiddler抓包8-打断点(bpu)
前言 先给大家讲一则小故事,在我们很小的时候是没有手机的,那时候跟女神聊天都靠小纸条.某屌丝A男对隔壁小王的隔壁女神C倾慕已久,于是天天小纸条骚扰,无奈中间隔着一个小王,这样小王就负责传小纸条了.有一 ...
- python 全栈开发,Day53(jQuery的介绍,jQuery的选择器,jQuery动画效果)
js总结 js: 1.ECMAScript5 ES5语法 2.DOM CRUD 获取 3种方式 id tag className //面向对象 对象 : 属性和方法 某个对象中 function $( ...
- 遍历集合的Iterator删除其中的元素
package list; import java.util.LinkedList; /* * 遍历集合的时候删除其中的元素 从后往前删,每次都删除的是最后一个元素,不涉及移位 */public cl ...
- oracle表分区的,分区操作,分区查询,子分区查询
一.摘要 有关表分区的一些维护性操作: 注:分区根据具体情况选择. 表分区有以下优点: 1.数据查询:数据被存储到多个文件上,减少了I/O负载,查询速度提高. 2.数据修剪:保存历史数据非常的理想. ...