[ZJOI2005]沼泽鳄鱼 矩阵乘法
题解:
乍一看还是挺懵逼的。和HH去散步很像,思路也是类似的。
复制一段我在HH去散步的题解里面写的一段话吧:
考虑f[i][j]表示i和j是否右边相连,有为1,否则为0,那么f同时可以表示从每个点出发走一步到其他点的方案数。
于是用一个和f长得一模一样的矩阵g来表示从每个点出发到其他点的方案数。
那么考虑g如何转移。
其实只要用g*f就可以表示一次转移了。
为什么?
设当前转移到了第t次,则g[i][j]表示i到j走t-1次的方案数(因为还没有更新)
那么矩阵乘法做了什么?
$g[i][j] = \sum_{l = 1}^{n}{g[i][l] * f[l][i]}$
也就是它枚举了点i走了t - 1次到l,然后再从l走一次到j的方案数。
是否能转移则要看l 到 j是否有边,而f[l][j]的意义刚好就是这样。
但这题有一些特殊的限制,就是会有食人鱼周期性的游动。
这样的话,转移就不再是一成不变的了,而是每天都有不同的不能去的地方,这样的话直接矩阵加速就做不了了。
但是暴力做矩阵乘法还是对的,因为这里的矩阵乘法实际上就是做一次DP
那么如何解决这个问题呢?
观察到题目给的一个特殊性质:周期只有2,3,4三种。gcd(2, 3, 4) = 12.这意味着每过12天,每天可走的路线又会与12天前重复。
所以如果我们把12天缩成1天,那么每天可走的路就是固定的了。
因此我们预处理出这12天每天可以走的路线,然后暴力转移12次,把12天的矩阵都浓缩成1个,然后再做矩阵乘法即可。
因为我们已经把12天缩成1天了,因此我们要乘的次数也变为了12分之一。
然后剩下的不能被12整除的天数就在末尾暴力乘即可。
由于矩阵乘法没有交换律,因此在暴力乘的过程中要格外注意顺序问题。
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 52
#define mod 10000 int n, m, s, t, k, num;
int g[AC][AC], go[AC][AC];//g记录连边情况,go表示第i条鱼,j时刻在哪 struct matrix{
int s[AC][AC];
}ans, f, p[], box; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} matrix cal(matrix x, matrix y)
{
for(R i = ; i <= n; i ++)
for(R j = ; j <= n; j ++)
{
box.s[i][j] = ;
for(R l = ; l <= n; l ++)
box.s[i][j] = (box.s[i][j] + x.s[i][l] * y.s[l][j]) % mod;
}
return box;
} inline void pre()
{
int a, b, T;
n = read(), m = read(), s = read() + , t = read() + , k = read();
for(R i = ; i <= m; i ++)//读入桥
{
a = read() + , b = read() + ;
g[a][b] = g[b][a] = ;
}
num = read();
for(R i = ; i <= num; i ++)//读入鱼
{
T = read();
for(R j = ; j < T; j ++) go[i][j] = read() + ;
for(R j = T; j < ; j ++) go[i][j] = go[i][j - T];
}
} void qpow(int have)
{
if(have <= ) return ;
while(have)
{
if(have & ) ans = cal(ans, f);
f = cal(f, f);
have >>= ;
}
} void work()
{
for(R i = ; i <= ; i ++)//枚举时刻
{
for(R j = ; j <= n; j ++)//枚举石墩
for(R l = ; l <= n; l ++) p[i].s[j][l] = g[j][l];
for(R j = ; j <= num; j ++)//枚举鱼
{
int x = go[j][i];//获取这条鱼在这个时刻在哪里
for(R l = ; l <= n; l ++) p[i].s[l][x] = ;//枚举从哪个石墩来到x
}
}
if(k <= )
{
ans = p[];
for(R i = ; i <= min(k, ); i ++) ans = cal(ans, p[i]);
if(k == ) ans = cal(ans, p[]);
printf("%d\n", ans.s[s][t]);
return ;
}
ans = p[];
for(R i = ; i <= ; i ++) ans = cal(ans, p[i]);
ans = cal(ans, p[]);
f = ans;
qpow(k / - );//因为有一个1在ans那
int b = k % ;
for(R i = ; i <= b; i ++) ans = cal(ans, p[i]);
printf("%d\n", ans.s[s][t]);
} int main()
{
// freopen("in.in", "r", stdin);
pre();
work();
// fclose(stdin);
return ;
}
[ZJOI2005]沼泽鳄鱼 矩阵乘法的更多相关文章
- 【BZOJ-1898】Swamp 沼泽鳄鱼 矩阵乘法
1898: [Zjoi2005]Swamp 沼泽鳄鱼 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1012 Solved: 566[Submit][S ...
- BZOJ 1898: [Zjoi2004]Swamp 沼泽鳄鱼(矩阵乘法)
可以发现,如果没有鳄鱼,那么就是裸地一道题,但是可以发现鳄鱼最多每12次重复,那么就少于12的那部分dp,其他的就矩阵乘法就行了 PS:第一次吧矩阵乘法AC了好开心QAQ CODE: #include ...
- [luogu2579 ZJOI2005] 沼泽鳄鱼(矩阵快速幂)
传送门 题目描述 潘塔纳尔沼泽地号称世界上最大的一块湿地,它地位于巴西中部马托格罗索州的南部地区.每当雨季来临,这里碧波荡漾.生机盎然,引来不少游客. 为了让游玩更有情趣,人们在池塘的中央建设了几座石 ...
- BZOJ 1898: [Zjoi2005]Swamp 沼泽鳄鱼 [矩阵乘法]
1898: [Zjoi2005]Swamp 沼泽鳄鱼 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1082 Solved: 602[Submit][S ...
- 【BZOJ1898】[Zjoi2005]Swamp 沼泽鳄鱼 矩阵乘法
[BZOJ1898][Zjoi2005]Swamp 沼泽鳄鱼 Description 潘塔纳尔沼泽地号称世界上最大的一块湿地,它地位于巴西中部马托格罗索州的南部地区.每当雨季来临,这里碧波荡漾.生机盎 ...
- 【BZOJ1898】[ZJOI2005]沼泽鳄鱼(矩阵快速幂,动态规划)
[BZOJ1898][ZJOI2005]沼泽鳄鱼(矩阵快速幂,动态规划) 题面 BZOJ 洛谷 题解 先吐槽,说好了的鳄鱼呢,题面里面全是食人鱼 看到数据范围一眼想到矩乘. 先不考虑食人鱼的问题,直接 ...
- 题解-[ZJOI2005]沼泽鳄鱼
题解-[ZJOI2005]沼泽鳄鱼 前置知识: 邻接矩阵 矩阵乘法 矩阵快速幂 [ZJOI2005]沼泽鳄鱼 给一个有 \(N\) 个点,\(M\) 条双向边的图 \(G\),其中有 \(NFish\ ...
- *HDU2254 矩阵乘法
奥运 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submissi ...
- *HDU 1757 矩阵乘法
A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
随机推荐
- ThinkPHP框架目录的介绍
library目录 Think目录 mvc
- 第四课:PHP 变量
变量指程序中使用的数值是可以变化的量,与常量(一旦被定义,就无法改变)相反. 变量是用于存储信息的"容器": 实例 <?php $x=5; $y=6; $z=$x+$y; e ...
- python学习之对象的三大特性
在面向对象程序设计中,对象可以看做是数据(特性)以及由一系列可以存取.操作这些数据的方法所组成的集合.编写代码时,我们可以将所有功能都写在一个文件里,这样也是可行的,但是这样不利于代码的维护,你总不希 ...
- 如何保证HashMap线程安全
可使用Java 1.5推荐的java.util.concurrent包ConcurrentHashMap来实现,内部不再使用类似HashTable的synchronized同步锁,而是使用Reentr ...
- Java基础——内部类
一.什么是内部类 将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类 内部类所在的类在编译成功后,会出现这样两个class文件:OuterClass.class和OuterClass$In ...
- JAVA大作业汇总1
JAVA大作业 代码 ``` package thegreatwork; import javafx.application.; import javafx.scene.control.; impor ...
- P2347 砝码称重
P2347 砝码称重 题目描述 设有1g.2g.3g.5g.10g.20g的砝码各若干枚(其总重<=1000), 输入输出格式 输入格式: 输入方式:a1 a2 a3 a4 a5 a6 (表示1 ...
- 【数据结构】 Queue 的简单实现
[数据结构] Queue 的简单实现 public class XQueue<T> { /// <summary> /// 第一个元素 /// </summary> ...
- UIButton内部子控件自定义布局-“UIEdgeInsets”
UIButton UIButton做frame动画时,不响应点击 在一个View内部加入几个按钮,然后改变这个view的frame来做动画,但是按钮不响应点击事件. 问题代码 __block CGRe ...
- 「暑期训练」「Brute Force」 Bitonix' Patrol (CFR134D1D)
题意 有n" role="presentation">nn个站点,排成圆形,每站间距m" role="presentation"> ...