P4159 [SCOI2009] 迷路 题解
P4159 [SCOI2009] 迷路
搬运工
题目链接
首先我们先考虑这道题的弱化版如何处理。假如所有的边权都是零和一。
这时他们的边权可以看做这两个点走一步到达之间的方案数。
而对于走 t 步,我们可以推出下列式子,
是不是很熟悉,我们发现它就是矩阵乘法的式子。
对于这个,这里有一道题P2233 [HNOI2002] 公交车路线,我们直接考虑矩阵加速,即可求出。
回到这道题
通过观察,我们发现他的每一个边权都很小,不会超过九(其实这就暗示了解法)
我们不妨考虑把每一个点拆成9个边权为1或0的点,可以这样想象(当然也有另外的拆法,大同小异)
我们可以将第一个点拆成
其中
而对于
在读入边权之前,我们需要将每个点的后八个假点每两个相邻的连接,边权为1 。
对于边权
这样就构造出了矩阵。然后直接跑矩阵快速幂就行。
对于求第
代码如下
/* * @Author: Ishar-zdl * @Date: 2023-10-14 15:03:04 * @Last Modified by: Ishar-zdl * @Last Modified time: 2023-10-15 07:51:30 */ #include<bits/stdc++.h> using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48); return x*f; } inline void write(int x){ if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+48); } const int mod=2009,N=95; struct mt{ int n,t[N][N]; inline mt(){memset(t,0,sizeof(t));} inline void clear(){ memset(t,0,sizeof(t)); for(int i=1;i<=n;++i)t[i][i]=1; } inline mt operator*(const mt&b)const{ mt res;int r;res.n=b.n; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j){ for(int k=1;k<=n;++k) res.t[i][j]+=t[i][k]*b.t[k][j]; res.t[i][j]%=mod; } return res; } inline mt operator^(int p)const{ mt res,x=*this;res.n=x.n; res.clear(); for(;p;p>>=1,x=x*x) if(p&1)res=res*x; return res; } }base; int main(){ // freopen("in.in","r",stdin); // freopen("out.out","w",stdout); int n=read(),q=read();base.n=9*n; int a; for(int i=1;i<=n;++i){ for(int zc=i*9-7;zc<=i*9;zc++) base.t[zc][zc-1]=1; for(int j=1;j<=n;++j){ scanf("%1d",&a); if(a) base.t[i*9-8][j*9-9+a]=1; } } base=base^q; write(base.t[1][n*9-8]); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】