codeforces 593E

来源:互联网 发布:mac什么视频播放器好 编辑:程序博客网 时间:2024/06/09 13:40

题目大意

给你一个nm20的地图,然后有三种询问或限制q10000
第一种,在(xi,yi)位置上从ti时刻有障碍。
第二种,在(xi,yi)位置上从ti时刻取消障碍。
第三种,询问ti(1,1)(xi,yi)的方案数对109+7取余.

保证ti>ti1

解题思路

这道题,很明显可以用矩阵乘法来转移状态,对于每次的询问或限制,我只需将转移矩阵乘上titi1次,就可以得到时间ti的方案数.

参考代码

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)#define maxn 25#define mo 1000000007#define mem(a,b) memset(a,b,sizeof(a))using namespace std;struct mat{    int a[maxn][maxn];}now;bool bz[maxn][maxn];int n,m,q,last;const int fx[4][2]={{0,1},{1,0},{0,-1},{-1,0}};int poi(int x,int y){    return (x-1)*m+y;}mat mul(mat x,mat y){    mat z;    mem(z.a,0);    fo(i,1,n*m)        fo(j,1,n*m)            fo(k,1,n*m)                z.a[i][j]=(z.a[i][j]+x.a[i][k]*1ll*y.a[k][j]) % mo;    return z;}mat pow(mat x,int y){    mat ret;    mem(ret.a,0);    fo(i,1,n*m) ret.a[i][i]=1;    while (y) {        if (y % 2 ==1) ret=mul(ret,x);        x=mul(x,x);        y /= 2;    }    return ret;}int main(){    scanf("%d%d%d",&n,&m,&q);    last=1;    fo(i,1,n*m) now.a[i][i]=1;    fo(i,1,q) {        int tp,x,y,t;        scanf("%d%d%d%d",&tp,&x,&y,&t);        mat tmp;        mem(tmp.a,0);        fo(j,1,n)            fo(k,1,m) {                fo(p,0,3) {                    int xx=j+fx[p][0],yy=k+fx[p][1];                    if (xx<=0 || yy<=0 || xx>n || yy>m) continue;                    if (bz[j][k] || bz[xx][yy]) tmp.a[poi(j,k)][poi(xx,yy)]=0;                    else tmp.a[poi(j,k)][poi(xx,yy)]=1;                }                if (bz[j][k]) tmp.a[poi(j,k)][poi(j,k)]=0;                else tmp.a[poi(j,k)][poi(j,k)]=1;            }        now=mul(now,pow(tmp,t-last));        if (tp==2) {            bz[x][y]=1;        }        else if (tp==3) {            bz[x][y]=0;        }        else {            printf("%d\n",now.a[1][poi(x,y)]);        }        last=t;    }    return 0;}
0 0
原创粉丝点击