Solution -「Code+#2」「洛谷 P4033」白金元首与独舞
\(\mathcal{Description}\)
link.
给定一个 \(n\times m\) 的网格图,一些格子指定了走出该格的方向(上下左右),而有 \(k\) 格可以任意指定走出方向。求指定的方案数,使得从任意格子都可以走出网格图。
\(n,m\le200;k\le300\)。
\(\mathcal{Solution}\)
令“走出边界”为走到一个特殊点,建图,其中未指定方向的点向四周连边,相当于求以特殊点为根的内向树个数,跑矩阵树定理即可。复杂度 \(\mathcal O(n^3m^3)\)。
考虑优化,生成树个数实质上只与不定向的点有关,所以直接预处理出每个不定向点向上/下/左/右走到的第一个不定向点,向其连边,再跑矩阵树。复杂度 \(\mathcal O(k^3)\)。
\(\mathcal{Code}\)
#include <cstdio>
#include <cstring>
#include <iostream>
const int MOD = 1e9 + 7, MAXN = 200, MAXP = 300;
int T, N, M, K[MAXP + 5][MAXP + 5], col[MAXN + 5][MAXN + 5], unk[MAXN + 5][MAXN + 5], cnt;
char gar[MAXN + 5][MAXN + 5];
inline int qkpow ( int a, int b, const int p = MOD ) {
int ret = 1;
for ( ; b; a = 1ll * a * a % p, b >>= 1 ) ret = 1ll * ret * ( b & 1 ? a : 1 ) % p;
return ret;
}
inline int det ( const int n ) {
int ret = 1, swp = 1;
for ( int i = 2; i <= n; ++ i ) {
for ( int j = i; j <= n; ++ j ) {
if ( K[j][i] ) {
if ( i ^ j ) std::swap ( K[i], K[j] ), swp *= -1;
break;
}
}
if ( ! ( ret = 1ll * ret * K[i][i] % MOD ) ) return 0;
for ( int j = i + 1, inv = qkpow ( K[i][i], MOD - 2 ); j <= n; ++ j ) {
int d = 1ll * K[j][i] * inv % MOD;
for ( int k = i; k <= n; ++ k ) K[j][k] = ( K[j][k] - 1ll * K[i][k] * d % MOD + MOD ) % MOD;
}
}
return ( ret * swp + MOD ) % MOD;
}
inline bool findLoop ( const int x, const int y, const int cur ) {
if ( x < 1 || x > N || y < 1 || y > M || gar[x][y] == '.' ) return false;
if ( col[x][y] == cur ) return true;
if ( col[x][y] ) return false;
col[x][y] = cur;
if ( gar[x][y] == 'L' ) return findLoop ( x, y - 1, cur );
if ( gar[x][y] == 'R' ) return findLoop ( x, y + 1, cur );
if ( gar[x][y] == 'U' ) return findLoop ( x - 1, y, cur );
if ( gar[x][y] == 'D' ) return findLoop ( x + 1, y, cur );
return false;
}
inline int findUnknown ( const int x, const int y ) {
if ( x < 1 || x > N || y < 1 || y > M ) return 1;
if ( unk[x][y] ) return unk[x][y];
int& ret = unk[x][y];
if ( gar[x][y] == 'L' ) ret = findUnknown ( x, y - 1 );
if ( gar[x][y] == 'R' ) ret = findUnknown ( x, y + 1 );
if ( gar[x][y] == 'U' ) ret = findUnknown ( x - 1, y );
if ( gar[x][y] == 'D' ) ret = findUnknown ( x + 1, y );
return ret;
}
inline void add ( const int s, int t ) {
if ( ! t ) t = 1;
++ K[s][s], -- K[s][t];
if ( K[s][t] < 0 ) K[s][t] += MOD;
}
int main () {
for ( scanf ( "%d", &T ); T --; ) {
memset ( K, 0, sizeof K );
memset ( col, 0, sizeof col );
memset ( unk, 0, sizeof unk );
scanf ( "%d %d", &N, &M ), cnt = 1;
for ( int i = 1; i <= N; ++ i ) {
scanf ( "%s", gar[i] + 1 );
for ( int j = 1; j <= M; ++ j ) {
if ( gar[i][j] == '.' ) {
unk[i][j] = ++ cnt;
}
}
}
bool loop = false;
for ( int i = 1, cur = 1; i <= N && ! loop; ++ i ) {
for ( int j = 1; j <= M && ! loop; ++ j ) {
loop |= findLoop ( i, j, cur ++ );
}
}
if ( loop ) { puts ( "0" ); continue; }
for ( int i = 1; i <= N; ++ i ) {
for ( int j = 1; j <= M; ++ j ) {
findUnknown ( i, j );
}
}
for ( int i = 1; i <= N; ++ i ) {
for ( int j = 1; j <= M; ++ j ) {
if ( gar[i][j] == '.' ) {
add ( unk[i][j], unk[i][j - 1] );
add ( unk[i][j], unk[i][j + 1] );
add ( unk[i][j], unk[i - 1][j] );
add ( unk[i][j], unk[i + 1][j] );
}
}
}
printf ( "%d\n", det ( cnt ) );
}
return 0;
}
Solution -「Code+#2」「洛谷 P4033」白金元首与独舞的更多相关文章
- 「区间DP」「洛谷P1043」数字游戏
「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...
- [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞
[LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞 试题描述 到河北省 见斯大林 / 在月光下 你的背影 / 让我们一起跳舞吧 うそだよ~ 河北省怎么可能有 Stalin. ...
- Solution -「JSOI 2019」「洛谷 P5334」节日庆典
\(\mathscr{Description}\) Link. 给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的). \(|S|\le3\time ...
- Solution -「洛谷 P4372」Out of Sorts P
\(\mathcal{Description}\) OurOJ & 洛谷 P4372(几乎一致) 设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...
- Solution -「POI 2010」「洛谷 P3511」MOS-Bridges
\(\mathcal{Description}\) Link.(洛谷上这翻译真的一言难尽呐. 给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...
- Solution -「APIO 2016」「洛谷 P3643」划艇
\(\mathcal{Description}\) Link & 双倍经验. 给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...
- 「洛谷P1516」 青蛙的约会
洛谷题号:P1516 出处:? 主要算法:数论 难度:4.4 思路分析: 典型的同余方程.由于是纬线,绕一圈是可以绕回来的,所以是可以取模的. 阅读题目,很容易得到同余方程$ x + tm ≡ y + ...
- 「BZOJ1038」「洛谷P2600」「ZJOI2008」瞭望塔 半平面交+贪心
题目链接 BZOJ/洛谷 题目描述 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安. 我们将H村抽象为一维的轮廓.如下图所示: 我们可以用一条山的上方 ...
- 「洛谷4197」「BZOJ3545」peak【线段树合并】
题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...
随机推荐
- xshell 6 的使用
1.前言 xshell是用来远程控制云服务器的linux系统的软件,装载window系统里面,可以向发送linux指令, 需要的关键信息:该系统设备的公网ip, 用户名 ,密码 2.软件下载 官网地址 ...
- php.ini配置文件中设置时区
date.timezone设置php5默认date.timezone为utc,改为date.timezone = PRC即可解决时间相差八小时的问题
- etcd的raft选取机制
etcd 是一个分布式的k/V存储系统.核心使用了RAFT分布式一致性协议.一致性这个概念,它是指多个服务器在状态达成一致,但是在一个分布式系统中,因为各种意外可能,有的服务器可能会崩溃或变得不可靠, ...
- Nginx日志通过Flume导入到HDFS中
关注公众号:分享电脑学习回复"百度云盘" 可以免费获取所有学习文档的代码(不定期更新) flume上传到hdfs: 当我们的数据量比较大时,比如每天的日志文件达到5G以上 使用ha ...
- js复制文本到剪贴板
execCommand是document的一个方法,返回值是布尔值(true,false) true表示操作被支持,false表示操作不被支持 此方法只针对于input和textarea,对里面的内容 ...
- Kube-OVN 0.6.0 发布,支持 IPv6、流量镜像及更多功能
Kube-OVN 是一个基于 OVN 的 Kubernetes 开源网络系统. 本次更新主要包含了以下内容: 1. 支持流量镜像 在安装 Kube-OVN 时可以开启 mirror 选项,会自动在每个 ...
- C#进程调用FFmpeg操作音视频
项目背景 因为公司需要对音视频做一些操作,比如说对系统用户的发音和背景视频进行合成,以及对多个音视频之间进行合成,还有就是在指定的源背景音频中按照对应的规则在视频的多少秒钟内插入一段客户发音等一些复杂 ...
- 彻彻底底地理解TCP三次握手和四次挥手的全部过程
三次握手 我们先提出一些问题,但是我们暂且不回答这些问题,下面我会尽我所能详尽地讲解TCP的三次握手过程,然后看完你可以在评论区留下你对问题的答案,我们可以一起探讨. 为什么要握手 为什么是三次而不是 ...
- visual studio进行机器学习与python编写
visual studio里的python安装之后自带一个虚拟环境 1.anaconda有些包版本无法到最新. 2.包管理器在安装卸载,强制停止后,包管理器会出问题,一直卸不掉那个包. 在卸载pyth ...
- Ajax_axios发送ajax请求
Ajax_axios发送ajax请求 这篇笔记主要讲一下axios基本的发送ajax请求的方法 axios在当前的前端行业里面是用的比较热门的一个 下面给大家分享一下它axios的一个基本用法 这段代 ...