[luogu 2579] [ZJOI2005]沼泽鳄鱼 {矩阵乘法}

题目

https://www.luogu.org/problemnew/show/P2579


解题思路

注意题目说食人鱼的周期是2,3,4,所以它们的 l c m lcm lcm 12 12 12周期。
根据巨佬的说法, k k k既然那么大,显然矩阵乘法。
A n s ( i ) = G ( 1 ) ∗ G ( 2 ) ∗ . . . G ( 12 ) ∗ G ( 1 ) ∗ G ( 1 ) ∗ G ( 2 ) ∗ . . . G ( n % 12 ) Ans(i)=G(1)*G(2)*...G(12)*G(1)*G(1)*G(2)*...G(n\%12) Ans(i)=G(1)G(2)...G(12)G(1)G(1)G(2)...G(n%12)
我们可以先设矩阵 G ( i ) . a [ x ] [ y ] G(i).a[x][y] G(i).a[x][y]为1,代表 x x x y y y之间在 i i i时刻可以行走。
然后根据题意,将某个时刻不能走的赋值为0即可。
最后套矩阵乘法模板,注意矩阵乘法不满足乘法交换律。


代码

#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,x,y) for(register int i=x;i<=y;++i)
using namespace std; 
const int N=60,T=12,expectation=10000; 
struct matrix{
	int a[N][N]; 
}f[T],ans;
int n,m,start,end,k,nfish,w,e; 
matrix operator * (matrix a,matrix b){
	matrix c; memset(c.a,0,sizeof(c.a));
	rep(i,0,N-1) rep(j,0,N-1) rep(g,0,N-1) (c.a[i][j]+=a.a[i][g]*b.a[g][j]%expectation)%=expectation; 
	return c; 
}
int main(){
	scanf("%d%d%d%d%d",&n,&m,&start,&end,&k); 
	rep(i,1,m) {
		int x,y;
		scanf("%d%d",&x,&y);
		rep(j,0,T-1) f[j].a[x][y]=f[j].a[y][x]=1; 
	}
	scanf("%d",&nfish); 
	rep(i,1,nfish){
		scanf("%d",&w); 
		rep(j,0,w-1){
			scanf("%d",&e); 
			for(register int g=j;g<T;g+=w){
				int lq=(g-1<0)?T-1:g-1; 	
				rep(q,0,n-1) f[lq].a[q][e]=0; 
			}
		}
	}
	ans.a[0][start]=1; 
	matrix F=f[0]; 
	rep(i,1,T-1) F=F*f[i]; 
	int le=k/T; 
	for(;le;F=F*F,le>>=1) if (le&1) ans=ans*F; 
	rep(i,0,(k%T)-1) ans=ans*f[i]; 
	printf("%d",ans.a[0][end]); 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值