zoukankan      html  css  js  c++  java
  • party

    Portal -->broken qwq

    Description

      这次怪兽大M受各路怪兽邀请参加聚会,被大M欺压的人类抓住机会想用陷阱抓捕大M。     可以将地图看作一个长n宽m的坐标系,大M在一开始处于(1,1)位置对于每一个时刻,大M可以朝上下左右走,或者不动。你作为人类的程序猿,被派出计算大M能参加聚会又能避开陷阱的方案数。你将接到总共q个3种类型的指令:

      1:x,y,t——人类截获怪兽的电报,发现大M将在t时刻参加一个位于(x,y)位置的舞会,保证(x,y)位置不存在一个陷阱。

    ​  2:x,y,t——人类在第t时刻在(x,y)位置放置了一个陷阱,保证(x,y)位置之前不存在一个陷阱。

      3:x,y,t——人类在第t时刻在(x,y)位置撤去了一个陷阱,保证(x,y)位置之前存在一个陷阱。

      对于每个类型1的指令,你需要输出大M从(1,1)出发,既能避开陷阱,又能参加舞会的方案数。因为这个方案数可能很大,你只需要输出方案数对10^9+7取模的余数。

      

      数据范围:1<=n*m<=20,1<=q<=1000 ,所有指令中2<=t<=10^9,保证各指令按t升序给出

      

    Solution

    (一开始看错题了以为只能往右或上走很开心敲完发现。。果然自己还是太naive。。。)

    ​  转移的话可以从上下左右以及自己转过来。。那。。比较容易想到矩乘吧

    ​  然后转移矩阵在更改陷阱情况的时候会改变,但是中间那段时间(也就是两次操作的间隔)是不变的,这段时间里面就直接用快速幂乘起来然后乘到答案里面去

      不要想着在每次询问的时候再求答案。。而是应该一路计算上去。。(怎么感觉好久没写这种题了然后开始智力退化。。一开始居然没想到。。我可能没救了qwq)

      

      代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=30,MOD=1e9+7;
    const int dx[5]={0,-1,0,1,0},dy[5]={0,0,1,0,-1};
    void add(int &x,int y){x=(1LL*x+MOD+y)%MOD;}
    int mul(int x,int y){return 1LL*x*y%MOD;}
    struct Mtrix{/*{{{*/
    	int a[N][N];
    	int n;
    	void init(int _n){n=_n;memset(a,0,sizeof(a));}
    	void setUnit(int _n){
    		n=_n;
    		for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) a[i][j]=i==j;
    	}
    	friend Mtrix operator * (Mtrix x,Mtrix y){
    		Mtrix ret;
    		ret.init(x.n);
    		for (int i=1;i<=ret.n;++i)
    			for (int j=1;j<=ret.n;++j){
    				for (int k=1;k<=ret.n;++k)
    					add(ret.a[i][j],mul(x.a[i][k],y.a[k][j]));
    			}
    		return ret;
    	}
    }ans,trans,ret,base;/*}}}*/
    int ok[N][N];
    int n,m,last,q;
    int Id(int x,int y){return (x-1)*m+y;}
    bool check(int x,int y){
    	if (x<1||x>n||y<1||y>m) return false;
    	return true;
    }
    void fill(){
    	int now,tmp,x,y;
    	trans.init(n*m);
    	for (int i=1;i<=n;++i)
    		for (int j=1;j<=m;++j){
    			if (!ok[i][j]) continue;
    			now=Id(i,j);
    			for (int d=0;d<5;++d){
    				x=i+dx[d]; y=j+dy[d];
    				if (!check(x,y)) continue;
    				tmp=Id(x,y);
    				trans.a[now][tmp]+=ok[x][y];
    			}
    		}
    }
    void ksm(int y){
    	ret.setUnit(n*m); base=trans;
    	for (;y;y>>=1,base=base*base)
    		if (y&1) ret=ret*base;
    }
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	scanf("%d%d%d",&n,&m,&q);
    	for (int i=1;i<=n;++i)
    		for (int j=1;j<=m;++j)
    			ok[i][j]=1;
    	int x,y,t,op;
    	last=1;
    	ans.init(n*m);
    	ans.a[1][1]=1;
    	fill();
    	for (int i=1;i<=q;++i){
    		scanf("%d%d%d%d",&op,&x,&y,&t);
    		if (op==1){
    			ksm(t-last);
    			ans=ans*ret;
    			printf("%d
    ",ans.a[Id(1,1)][Id(x,y)]);
    			last=t;
    		}
    		else if (op==2){
    			ksm(t-last);
    			ans=ans*ret;
    			last=t;
    			ok[x][y]=0;
    			fill();
    		}
    		else{
    			ksm(t-last);
    			ans=ans*ret;
    			last=t;
    			ok[x][y]=1;
    			fill();
    		}
    	}
    
    }
    
  • 相关阅读:
    Flask莫名其妙特别慢
    MySQL老是提示视图没有主键
    Mysql写入中文出错
    Sqlite向MySql导入数据
    大智慧专业财务PFFIN(N,M)函数N的取值一览表
    js的技巧
    拍拍贷年化收益率的推算
    Sqlite的多表连接更新
    Kali Linux 64位架构安装Veil-Evasion
    修改Kali Linux 2020.1主题颜色
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9384229.html
Copyright © 2011-2022 走看看