构造如下一张无向图:

1.点集大小为$(n+1)(m+1)$,即所有格点

2.边集大小为$nm$,即所有镜子所连结的两个格点

对于一个确定的镜子状态,即可确定上图,那么来考虑什么样的图是合法的

结论:如果将这些点黑白染色,显然不存在连结黑色和白色点的边,之后合法当且仅当黑色点恰好构成生成树或白色点恰好构成生成树

由于两者不可能同时构成生成树(这意味着有$(n+1)(m+1)-2$条边,边数不足)

以黑色为例,对于一个未确定的镜子,也就是一条边是否存在,不难发现这就是一个生成树计数,对于强制存在的边预先缩点即可,由于最后至多新增$k$条边,即若缩点后连通块数多于$k+1$无解($k$为$*$个数)

根据矩阵树定理计算,复杂度显然是$o(k^{3})$,缩点复杂度为$o(nm\log nm)$,即可通过

下面考虑前面的结论,简单的说明一下:

为了方便,将最外面的一圈边界也看作镜子并连边,然后即构成了一张平面图

对于平面图中的封闭图形,显然光线无法穿过多个封闭图形,接下来我们证明一个封闭图形中恰好有一条光线,且覆盖了其中所有位置

证明比较简单,只需要找到一个与光线相邻且未被覆盖的位置,从该处引出一条光线就会导致矛盾

换言之,与边界线在同一个封闭图形内的另一个出口就是其结束的位置

这也就等价于边界上所有黑点(或白点)相邻两点连通,那么即构成一个仅含相邻两段边界线的封闭图形,同时如果不包含所有黑点,那么外面这一圈相邻两点的路径有交,必然构成一个不包含边界的封闭图形,无法被覆盖

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 105
4 vector<pair<int,int> >v;
5 int n,m,k,mod,a[N<<1][N<<1],pos[N*N],f[N*N];
6 char s[N][N];
7 int id(int x,int y){
8 return x*(m+1)+y+1;
9 }
10 int find(int k){
11 if (k==f[k])return k;
12 return f[k]=find(f[k]);
13 }
14 bool merge(int x,int y){
15 x=find(x),y=find(y);
16 if (x==y)return 0;
17 f[x]=y;
18 return 1;
19 }
20 int pow(int n,int m){
21 int s=n,ans=1;
22 while (m){
23 if (m&1)ans=1LL*ans*s%mod;
24 s=1LL*s*s%mod;
25 m>>=1;
26 }
27 return ans;
28 }
29 int guess(int n){
30 int ans=1;
31 for(int i=1;i<=n;i++){
32 int k=-1;
33 for(int j=i;j<=n;j++)
34 if (a[j][i]){
35 k=j;
36 break;
37 }
38 if (k<0)return 0;
39 if (k!=i){
40 ans=mod-ans;
41 for(int j=i;j<=n;j++)swap(a[i][j],a[k][j]);
42 }
43 ans=1LL*ans*a[i][i]%mod;
44 int s=pow(a[i][i],mod-2);
45 for(int j=i;j<=n;j++)a[i][j]=1LL*a[i][j]*s%mod;
46 for(int j=i+1;j<=n;j++){
47 int s=a[j][i];
48 for(int k=i;k<=n;k++)a[j][k]=(a[j][k]-1LL*s*a[i][k]%mod+mod)%mod;
49 }
50 }
51 return ans;
52 }
53 int calc(int p){
54 for(int i=0;i<=n;i++)
55 for(int j=0;j<=m;j++)
56 if ((i+j)%2==p)f[id(i,j)]=id(i,j);
57 v.clear();
58 for(int i=0;i<n;i++)
59 for(int j=0;j<m;j++)
60 if ((i+j)%2==p){
61 if (s[i][j]=='*')v.push_back(make_pair(id(i,j),id(i+1,j+1)));
62 if (s[i][j]=='\\'){
63 if (!merge(id(i,j),id(i+1,j+1)))return 0;
64 }
65 }
66 else{
67 if (s[i][j]=='*')v.push_back(make_pair(id(i,j+1),id(i+1,j)));
68 if (s[i][j]=='/'){
69 if (!merge(id(i,j+1),id(i+1,j)))return 0;
70 }
71 }
72 pos[0]=0;
73 for(int i=0;i<=n;i++)
74 for(int j=0;j<=m;j++)
75 if (((i+j)%2==p)&&(f[id(i,j)]==id(i,j)))pos[id(i,j)]=++pos[0];
76 if (pos[0]>k+1)return 0;
77 memset(a,0,sizeof(a));
78 for(int i=0;i<v.size();i++){
79 int x=pos[find(v[i].first)],y=pos[find(v[i].second)];
80 if (x<pos[0])a[x][x]=(a[x][x]+1)%mod;
81 if (y<pos[0])a[y][y]=(a[y][y]+1)%mod;
82 if ((x<pos[0])&&(y<pos[0])){
83 a[x][y]=(a[x][y]+mod-1)%mod;
84 a[y][x]=(a[y][x]+mod-1)%mod;
85 }
86 }
87 return guess(pos[0]-1);
88 }
89 int main(){
90 scanf("%d%d%d",&n,&m,&mod);
91 for(int i=0;i<n;i++){
92 scanf("%s",s[i]);
93 for(int j=0;j<m;j++)
94 if (s[i][j]=='*')k++;
95 }
96 printf("%d",(calc(0)+calc(1))%mod);
97 }

[cf578F]Mirror Box的更多相关文章

  1. [codeforces 241]C. Mirror Box

    [codeforces 241]C. Mirror Box 试题描述 Mirror Box is a name of a popular game in the Iranian National Am ...

  2. 「CF578F」 Mirror Box

    description CF578F solution 考虑转化题目的要求 1.对于任意一条边,都存在一条从界垂直射入的光线,经过反射穿过这条边. 当图中有环时,环内的边一定不满足条件,而在不存在环时 ...

  3. 矩阵树定理&BEST定理学习笔记

    终于学到这个了,本来准备省选前学来着的? 前置知识:矩阵行列式 矩阵树定理 矩阵树定理说的大概就是这样一件事:对于一张无向图 \(G\),我们记 \(D\) 为其度数矩阵,满足 \(D_{i,i}=\ ...

  4. 为 Virtual Box 中的 CentOS 6.6 配置本地DVD光盘做yum软件源

    因为virtual box 中的centos配置host-only共享win7上网,配置失败,所以只能使用Centos的 DVD 光盘来配置yum软件源.不然就没得完了. 1. 首先要在virtual ...

  5. Box/坐标/方向/Row

    1.Box, 我们在做design planning的第一步就是确定floorplan的box,也就是设计的区域.这个区域可以划分为三个边界,如下图所示: 上图中,按对应的颜色框框可以分为:Die B ...

  6. Virtual Box配置CentOS7网络(图文教程)

    之前很多次安装CentOS7虚拟机,每次配置网络在网上找教程,今天总结一下,全图文配置,方便以后查看. Virtual Box可选的网络接入方式包括: NAT 网络地址转换模式(NAT,Network ...

  7. Linux监控工具介绍系列——OSWatcher Black Box

      OSWatcher Balck Box简介 OSWatcher Black Box (oswbb)是Oracle开发.提供的一个小巧,但是实用.强大的系统工具,它可以用来抓取操作系统的性能指标,用 ...

  8. 使用packer制作vagrant centos box

    使用packer制作vagrant box:centos 制作vagrant box,网上有教程,可以自己step by step的操作.不过直接使用虚拟在VirtualBox中制作vagrant b ...

  9. 快速打造跨平台开发环境 vagrant + virtualbox + box

    工欲善其事必先利其器,开发环境 和 开发工具 就是 我们开发人员的剑,所以我们需要一个快并且好用的剑 刚开始做开发的时候的都是把开发环境 配置在 自己的电脑上,随着后面我们接触的东西越来越多,慢慢的电 ...

随机推荐

  1. 网络基础--简单理解什么是DNS? TCP? UDP? Http? Socket?

    什么是IP 协议?  协议就是为了实现网络通信而创建的一系列规范.  通常我们的网络模型从上到下共分为4层: 应用层, 传输层, 网络层 和数据链路层. IP协议属于网络层协议,它精确定义了网络通信中 ...

  2. C++学习 2 指针

    指针:指针保存的是数据的地址: #include<iostream> using namespace std; int main() { //1.定义指针 int a = 10; //指针 ...

  3. 如何在另一台设备上搭建python接口自动化项目所需要的第三方库

    1.如何将当前项目引用的第三方库导出,在新建项目时,选择New environment using>Virtualenv 2.然后右键选择open in terminal:输入命令:pip fr ...

  4. 文本域textarea的一个小细节

    文本域代码在编写时,最好写在一行上,就像: 如果没写在一行上,如: 那么就会在后续生成的页面上输入的时候就会产生一段空白无法删除: 这是写文本框的时候的一个小细节

  5. Linux 命令后&的作用

    cp $filename /dev/ & & 代表非阻塞方式拷贝文件,如果不加& 则必须等到执行完该指令后才能执行后来的指令.

  6. springboot 事务执行全流程分析

    springboot 事务执行全流程分析 目录 springboot 事务执行全流程分析 1. 事务方法执行前的准备工作 2. 业务代码的调用 3. 事务方法执行后处理 4. 业务代码在事务和非事务中 ...

  7. DevOps 时代的高效测试之路

    10 月 22 日,2021 届 DevOps 国际峰会在北京顺利召开,来自国内外的顶级技术专家共同畅谈 DevOps 体系与方法.过程与实践.工具与技术.CODING 测试及研发流程管理产品总监程胜 ...

  8. python查询对像所有方法

    鉴于学习时好多参数对像都不知道是什么玩意有什么方法,搜了半天一个 """arg为一个对像,下面是打印所有对像方法"""for i, func ...

  9. elasticsearch父子文档处理(join)

    elasticsearch父子文档处理 join 一.背景 二.需求 三.前置知识 四.实现步骤 1.创建 mapping 2.添加父文档数据 3.添加子文档 4.查询文档 1.根据父文档id查询它下 ...

  10. Noip模拟13 2021.7.13:再刚题,就剁手&&生日祭

    T1 工业题 这波行列看反就非常尴尬.....口糊出所有正解想到的唯独行列看反全盘炸列(因为和T1斗智斗勇两个半小时...) 这题就是肯定是个O(n+m)的,那就往哪里想,a,b和前面的系数分开求,前 ...