矩阵加速dp
一般先想dp
一个点的状态等于它自己加上四周没有猫的格子的状态 简单粗暴的dp
然后构造矩阵,长n( imes)m,宽(n imes)m存储时把两维压成一维存储
若(x1,y1)能到达(x2,y2)则矩阵中即为1否则为0简单粗暴的矩阵
然后每修改一次就重构矩阵,卡速米跳过时间段即可
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define int long long
using namespace std;
const int mod=1000000007;
struct sett{
int k[50][50];
}ans,base;
int N,n,m,q;
int mp[25][25];
sett mul(sett a,sett b){
sett c;
memset(c.k,0,sizeof(c.k));
for(int i=1;i<=N;i++)
for(int r=1;r<=N;r++)
for(int p=1;p<=N;p++)
c.k[i][r]=(c.k[i][r]+a.k[i][p]*b.k[p][r])%mod;
return c;
}
void qpow(int b){
for(;b;b>>=1,base=mul(base,base))if(b&1)ans=mul(base,ans);
}
void build(){
for(int i=1;i<=N;i++)
for(int r=1;r<=N;r++){
int a=((i-1)/m)+1,b=(i-1)%m+1;
int A=((r-1)/m)+1,B=(r-1)%m+1;
int dist=abs(A-a)+abs(B-b);
if(mp[a][b]==0&&mp[A][B]==0&&dist<=1)base.k[i][r]=1;
else base.k[i][r]=0;
}
}
signed main(){
scanf("%lld%lld%lld",&n,&m,&q);
N=n*m;
ans.k[1][1]=1;
int plk=1;
while(q--){
build();
int op,x,y,t;
scanf("%lld%lld%lld%lld",&op,&x,&y,&t);
qpow(t-plk);
plk=t;
if(op==2)ans.k[(x-1)*m+y][1]=0,mp[x][y]=1;
if(op==3)ans.k[(x-1)*m+y][1]=0,mp[x][y]=0;
if(op==1)printf("%lld
",ans.k[(x-1)*m+y][1]);
}
}