BZOJ5133: [CodePlus2017年12月]白金元首与独舞

BZOJ5133: [CodePlus2017年12月]白金元首与独舞

https://lydsy.com/JudgeOnline/problem.php?id=4894

分析:

  • 可以发现原来就确定的那些格子不会影响答案,除非有某个格子会使得出现环。
  • 预处理出来每个格子会走到哪里,对每个不确定的格子向四周都走一下,向他们连边。
  • 设走到外部为根,转化成有向树计数问题。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 305
#define mod 1000000007
typedef long long ll;
ll qp(ll x,ll y) {
	ll re=1; for(;y;y>>=1,x=x*x%mod) if(y&1) re=re*x%mod; return re;
}
char g[N][N];
int n,vis[N][N],col[N][N],m;
int FLG=0,idx[N][N],to[N][N],tot;
ll a[N][N];
int dfs(int x,int y) {
	if(vis[x][y]) {FLG=1; return -1;}
	if(g[x][y]=='.') return idx[x][y];
	if(x<1||x>n||y<1||y>m) return tot;
	if(to[x][y]) return to[x][y];
	vis[x][y]=1;
	if(g[x][y]=='L') to[x][y]=dfs(x,y-1);
	else if(g[x][y]=='R') to[x][y]=dfs(x,y+1);
	else if(g[x][y]=='U') to[x][y]=dfs(x-1,y);
	else to[x][y]=dfs(x+1,y);
	vis[x][y]=0;
	return to[x][y];
}
int tx[]={0,1,0,-1};
int ty[]={1,0,-1,0};
ll Gauss(int n) {
	int i,j,k,flg=0; ll del,ans=1;
	for(i=1;i<=n;i++) {
		for(j=i;j<=n&&!a[j][i];j++) ;
		if(j>n) continue;
		if(i!=j) {
			for(k=i;k<=n;k++) swap(a[i][k],a[j][k]); flg^=1;
		}
		for(j=i+1;j<=n;j++) if(a[j][i]) {
			del=a[j][i]*qp(a[i][i],mod-2)%mod;
			for(k=i;k<=n;k++) a[j][k]=(a[j][k]-a[i][k]*del)%mod;
		}
	}
	for(i=1;i<=n;i++) ans=ans*a[i][i]%mod;
	if(flg) ans=-ans;
	return (ans+mod)%mod;
}
int main() {
	/*freopen("a.in","r",stdin);
	freopen("a.out","w",stdout)*/
	int T;
	scanf("%d",&T);
	while(T--) {
		memset(vis,0,sizeof(vis));
		memset(a,0,sizeof(a));
		memset(to,0,sizeof(to));
		memset(idx,0,sizeof(idx));
		scanf("%d%d",&n,&m);
		int i,j;
		for(i=1;i<=n;i++) scanf("%s",g[i]+1);
		FLG=0;
		tot=0;
		for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(g[i][j]=='.') idx[i][j]=++tot;
		tot++;
		for(i=1;i<=n;i++) {
			for(j=1;j<=m;j++) if(g[i][j]!='.') {
				dfs(i,j);		
			}
		}
		if(FLG) {puts("0"); continue;}
		for(i=1;i<=n;i++) {
			for(j=1;j<=m;j++) if(g[i][j]=='.') {
				int x=i,y=j;
				int k;
				for(k=0;k<4;k++) {
					int dx=x+tx[k], dy=y+ty[k];
					if(g[dx][dy]=='.') to[x][y]=idx[dx][dy];
					else if(dx<1||dx>n||dy<1||dy>m) to[x][y]=tot;
					else to[x][y]=to[dx][dy];
					a[idx[x][y]][idx[x][y]]++;
					a[ to[x][y]][idx[x][y]]--;
				}
			}
		}
		/*for(i=1;i<tot;i++) {
			for(j=1;j<tot;j++) printf("%lld ",a[i][j]);
			puts("");
		}*/
		printf("%lld\n",Gauss(tot-1));
	}
}
posted @ 2019-01-06 18:16  fcwww  阅读(205)  评论(0编辑  收藏  举报