[矩阵乘法]JZOJ 2288 沼泽鳄鱼
Posted mastervan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[矩阵乘法]JZOJ 2288 沼泽鳄鱼相关的知识,希望对你有一定的参考价值。
分析
考试的时候总觉得这题在哪里见过……然后做法想好后才想起来是J爷的矩阵乘法习题
我们可以发现矩乘的过程其实是一个类似于floyd的过程,可以把一个点到另一个点的路径总长得出来,那么在边权为1的情况下就是方案数
然后一看K大也能大概猜出来是矩乘,可是不会打 菜哭了
因为鱼是有循环节的,我们可以把循环节的最小公倍数作为快速幂的基准
先处理出一个从1到12所有时间的情况都乘在一起的矩阵T
然后快速幂^k/12
最后再逐个乘上k%12的矩阵T即可
#include <iostream> #include <cstdio> #include <memory.h> using namespace std; typedef long long ll; const int N=60; const ll P=1e4; int n,fish,m,st,ed,K,fp[N][N]; bool use[N]; struct Rect ll a[N][N]; ll *operator [](int i)return a[i]; void In() for (int i=0;i<n;i++) a[i][i]=1; void Empty() memset(a,0,sizeof a); Rect operator * (Rect b) Rect c;c.Empty(); for (int i=0;i<n;i++) for (int j=0;j<n;j++) for (int k=0;k<n;k++) if (!use[k]) (c[i][j]+=a[i][k]*b[k][j]%P)%=P; return c; f,ans,e; Rect Ksm(Rect a,int y) Rect ans; memset(use,0,sizeof use);ans.In(); while (y) if (y&1) ans=ans*a; a=a*a; y>>=1; return ans; void Pre_Process(int x) memset(use,0,sizeof use); for (int i=1;i<=fish;i++) use[fp[i][(x-1)%fp[i][0]+1]]=1; int main() scanf("%d%d%d%d%d",&n,&m,&st,&ed,&K);e.In();ans.In(); for (int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),f[u][v]++,f[v][u]++; scanf("%d",&fish); for (int i=1;i<=fish;i++) scanf("%d",&fp[i][0]); for (int j=1;j<=fp[i][0];j++) scanf("%d",&fp[i][j]); for (int i=1;i<=12;i++) Pre_Process(i),e=e*f; ans=ans*Ksm(e,K/12); for (int i=1;i<=K%12;i++) Pre_Process(i),ans=ans*f; printf("%lld",ans.a[st][ed]);
以上是关于[矩阵乘法]JZOJ 2288 沼泽鳄鱼的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1898[Zjoi2005]Swamp 沼泽鳄鱼 矩阵乘法
P2579 [ZJOI2005]沼泽鳄鱼(邻接矩阵,快速幂)
bzoj 1898 [Zjoi2005]Swamp 沼泽鳄鱼——矩阵快速幂