列表

详情


NC14758. 白金元首与独舞

描述

元首把花园分为 n 行 m 列的网格。每个格子中都可以放置一个标识,指向上、下、左、右四个方向中的任意一个。元首位于一个格子时,会按照其中标识所指的方向进入周围的格子,或者走出花园(即目的格子不在网格之内)。举个例子 —— 对于下面的放置方式,元首从第 3 行第 2 列的格子开始,会沿着以红色标出的路径走出花园;从第 2 行第 2 列的格子开始,则会在以蓝色标出的环路内不断地行走。

元首已经设计好了大部分格子的标识。元首用字符 L、R、U、D 分别表示指向左、右、上、下四个方向的标识,用字符 . 表示未决定的格子。现在,元首希望将每个 . 替换为 L、R、U、D 中任意一种,使得从花园中的任意一个格子出发,按照上述规则行走,都可以最终走出花园。
你需要编写程序帮助元首计算替换的不同方案数。两个方案不同当且仅当存在一个格子,使得两个方案中该格子内的标识不同。当然,由于答案可能很大,只需给出方案数除以 109+7 所得的余数即可。

输入描述

输入的第一行包含一个正整数 T —— 测试数据的组数。接下来包含 T 组测试数据,格式如下,测试数据间没有空行。
第 1 行:两个空格分隔的正整数 n、m —— 依次表示花园被分成的行数和列数。
接下来 n 行:每行一个长度为 m 的由字符 L、R、U、D 和 . 组成的字符串 —— 表示花园内已经确定的格子状态。

输出描述

对于每组测试数据输出一行 —— 满足条件的方案数除以 109 + 7 所得的余数。 

示例1

输入:

5
3 9
LLRRUDUUU
LLR.UDUUU
LLRRUDUUU
4 4
LLRR
L.LL
RR.R
LLRR
4 3
LRD
LUL
DLU
RDL
1 2
LR
2 2
..
..

输出:

3
8
0
1
192

说明:

第 1 组数据中,将惟一的 . 替换成 R、U 或 D 均满足要求。
第 2 组数据中,将左上方和右下方的两个 . 分别替换成 LR、LU、LD、UR、UU、UD、DR 或 DD 均满足要求。
第 3 组数据中,没有待决定的格子,原本的安排会使得元首陷入无尽的环路,故答案为 0。该组数据与【题目描述】中的例子相同。
第 4 组数据中,也没有待决定的格子,但原本的安排已经满足要求,故答案为 1。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 38ms, 内存消耗: 9568K, 提交时间: 2020-08-09 12:48:56

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=505;
ll T,n,m,tot,cnt,fa[maxn*maxn],id[maxn][maxn];
ll End[maxn*maxn],Next[maxn*maxn],Last[maxn*maxn];
ll bl[maxn*maxn],G[maxn][maxn];
char s[maxn][maxn];
bool flag;
void Addedge(ll x,ll y)
{
    End[++cnt]=y;
    Next[cnt]=Last[x],Last[x]=cnt;
}
void DFS(ll x)
{
    fa[x]=tot;
    for(ll i=Last[x];i;i=Next[i])
        if(fa[End[i]]<0) DFS(End[i]);
}
ll Gauss(ll n)
{
    ll temp=1,mark=0;
    for(ll i=1;i<=n;i++)
    {
        for(ll j=i+1;j<=n;j++)
            while(G[j][i])
            {
                ll t=G[i][i]/G[j][i];
                for(ll k=i;k<=n;k++) G[i][k]=(G[i][k]-t*G[j][k]%mod+mod)%mod;
                swap(G[i],G[j]),mark^=1;
            }
        temp=temp*G[i][i]%mod;
    }
    if(mark) temp=mod-temp;
    return (temp%mod+mod)%mod;
}
int main()
{
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld%lld",&n,&m),tot=cnt=flag=0;
        memset(Last,0,sizeof(Last));
        memset(fa,-1,sizeof(fa));
        memset(id,0,sizeof(id));
        for(ll i=1;i<=n;i++) scanf("%s",s[i]+1);
        for(ll i=1;i<=n;i++)
            for(ll j=1;j<=m;j++) id[i][j]=(i-1)*m+j;
        for(ll i=1;i<=n;i++)
            for(ll j=1;j<=m;j++)
                if(s[i][j]!='.')
                {
                    ll tx=i,ty=j;
                    if(s[i][j]=='U') tx--;
                    else if(s[i][j]=='D') tx++;
                    else if(s[i][j]=='L') ty--;
                    else ty++;
                    Addedge(id[tx][ty],id[i][j]);
                }
        DFS(0);
        for(ll i=1;i<=n;i++)
            for(ll j=1;j<=m;j++)
                if(s[i][j]=='.') tot++,DFS(id[i][j]);
        for(ll i=1;i<=n&&!flag;i++)
            for(ll j=1;j<=m&&!flag;j++)
                if(fa[id[i][j]]<0) flag=true;
        if(flag){puts("0");continue;}
        if(!tot){puts("1");continue;}
        memset(G,0,sizeof(G));
        for(ll i=1;i<=n;i++)
            for(ll j=1;j<=m;j++)
                if(s[i][j]=='.')
                {
                    ll f=fa[id[i][j]];
                    if(fa[id[i-1][j]]!=f) G[f][f]++,G[f][fa[id[i-1][j]]]--;
                    if(fa[id[i][j-1]]!=f) G[f][f]++,G[f][fa[id[i][j-1]]]--;
                    if(fa[id[i+1][j]]!=f) G[f][f]++,G[f][fa[id[i+1][j]]]--;
                    if(fa[id[i][j+1]]!=f) G[f][f]++,G[f][fa[id[i][j+1]]]--;
                }
        printf("%lld\n",Gauss(tot));
    }
    return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 533ms, 内存消耗: 1268K, 提交时间: 2022-08-18 14:00:37

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<ctime>
using namespace std;
#define P 1000000007
#define ll long long
const int dx[]={-1,0,1,0},dy[]={0,-1,0,1};
int Pow(int x,int y)
{
	int s=1;
	for(;y;y>>=1,x=(ll)x*x%P)if(y&1)s=(ll)s*x%P;
	return s;
}
int t,n,m,N,i,j,k,l,ans,v[205][205],f[205][205],a[305][305];
char c[205][205];
int dfs(int x,int y)
{
	if(v[x][y]==2)return f[x][y];
	if(v[x][y]==1)return -1;
	v[x][y]=1;
	if(c[x][y]=='.')f[x][y]=++N;
	else if(c[x][y]=='L')f[x][y]=dfs(x,y-1);
	else if(c[x][y]=='R')f[x][y]=dfs(x,y+1);
	else if(c[x][y]=='U')f[x][y]=dfs(x-1,y);
	else f[x][y]=dfs(x+1,y);
	v[x][y]=2;
	return f[x][y];
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		memset(c,0,sizeof(c));
		N=0;
		for(i=1;i<=n;i++)scanf("%s",c[i]+1);
		memset(v,0,sizeof(v));
		memset(f,0,sizeof(f));
		memset(a,0,sizeof(a));
		for(i=1;i<=n;i++)v[i][0]=v[i][m+1]=2;
		for(i=1;i<=m;i++)v[0][i]=v[n+1][i]=2;
		for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(!v[i][j])if(!~dfs(i,j))goto xxx;
		for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(c[i][j]=='.')for(k=0;k<4;k++)
		{
			a[f[i+dx[k]][j+dy[k]]][f[i][j]]--;
			a[f[i][j]][f[i][j]]++;
		}
		for(i=1;i<=N;i++)for(j=1;j<=N;j++)if(a[i][j]<0)a[i][j]+=P;
		for(i=ans=1;i<N;i++)
		{
			for(j=i;j<=N;j++)if(a[j][i])break;
			if(j>N)break;
			if(j!=i)for(ans=P-ans,k=i;k<=N;k++)swap(a[j][k],a[i][k]);
			for(j=i+1,l=Pow(a[i][i],P-2);j<=N;j++)for(k=N;k>=i;k--)a[j][k]=(a[j][k]-(ll)a[i][k]*a[j][i]%P*l%P+P)%P;
		}
		for(i=1;i<=N;i++)ans=(ll)ans*a[i][i]%P;
		cout<<ans<<endl;
		continue;
		xxx:puts("0");
	}
	return 0;
}

上一题