n,m<=200,n*m的方阵,有ULRD表示在这个格子时下一步要走到哪里,有一些待决策的格子用.表示,可以填ULRD任意一个,问有多少种填法使得从每个格子出发都能走出这个方阵,答案取模。保证未确定的格子<=300。

。。。一脸懵逼地写了原本30实际20的暴力然后跪着啃了下论文

然而什么都没啃懂不如结论记下来:

首先矩阵行列式的定义:一个n*n的矩阵,行列式值为$\sum_{b是n的一个排列} \ \ \ \ \ ( (-1)^{b的逆序对数} \ \ \ \ \ * \prod_{i=1}^{n} A_{i,b_i})$

矩阵A行列式的性质:

|A|=|A的转置|

|AB|=|A||B|

|A|+|B|=|A和B的某一行加起来其他不变的矩阵|

交换两行得B,|B|=-|A|,因为每次计算一个排列时逆序对数都相差1。

A的某行乘个x得B,|B|=x|A|。

A的某行乘某个数加到另一行上得B,|B|=|A|。由第三条可得。

每行每列和为0的矩阵行列式为0。

由四五六条可用高斯消元计算行列式。

基尔霍夫矩阵:

无向图:矩阵对角线上是度数,其他如果对应边存在就是-1,不然就是0。

有向图:矩阵对角线上是入度,其他如果对应边存在就是-1,不然就是0。

矩阵树定理:一个无向图的基尔霍夫矩阵的任意一个n-1阶的子矩阵,即删掉了第i行和第i列,的行列式是这个图的生成树个数。

一个有向图以点i为根的生成树个数是基尔霍夫矩阵去掉第i行和第i列剩下的矩阵的行列式。

如果图为多图,作如下修改:

当$i \neq j$而有重边时,把邻接矩阵的1改成$i$,$j$间的边数;

当$i = j$而有自环时,自环不可能出现在生成树中,统计度数时记得忽略之。

嗯然后就是这道题。

首先,如果在外界虚拟一个节点,把所有指出去的格子都指向它,把所有确定格子向指向的点连边,可得一个有向图。

然后,待确定的点向四个方向都连边,求这个图以外界点为根的反向的树形图即可。为什么呢,首先确定的格子的边一定会选到,因为每个格子只有一条出边,不然他就和其他点断掉了;其次那些待确定的格子为了形成树,只会在四个方向里选一个。

嗯这样只能拿50分。

可以发现那些已经确定的点是多余的,可以缩掉。也就是给所有待确定格子编号,外界点编号0,然后预处理他往上下左右走能遇到的第一个有编号的格子,朝他们连边即可。

然后就大功告成了。

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. #include<stdlib.h>
  5. //#include<queue>
  6. #include<math.h>
  7. //#include<time.h>
  8. //#include<iostream>
  9. using namespace std;
  10.  
  11. int n,m,K,T;
  12. const int mod=1e9+;
  13. #define maxn 311
  14. int pos[maxn][maxn],who[maxn][maxn],place[maxn][]; char mp[maxn][maxn];
  15.  
  16. int powmod(int a,int b)
  17. {
  18. int ans=;
  19. while (b)
  20. {
  21. if (b&) ans=1ll*ans*a%mod;
  22. a=1ll*a*a%mod;
  23. b>>=;
  24. }
  25. return ans;
  26. }
  27.  
  28. struct Mat
  29. {
  30. int num[maxn][maxn];
  31. void clear() {memset(num,,sizeof(num));}
  32. }mat;
  33. int gauss()
  34. {
  35. int ans=;
  36. for (int i=;i<=K;i++)
  37. {
  38. int id=i;
  39. for (int j=i+;j<=K;j++) if (fabs(mat.num[j][i])>fabs(mat.num[id][i])) id=j;
  40. if (id!=i)
  41. {
  42. ans=1ll*ans*(mod-)%mod;
  43. for (int j=i;j<=K;j++) {int t=mat.num[i][j]; mat.num[i][j]=mat.num[id][j]; mat.num[id][j]=t;}
  44. }
  45. int tmp=powmod(mat.num[i][i],mod-);
  46. for (int j=i+;j<=K;j++)
  47. for (int k=K;k>=i;k--)
  48. mat.num[j][k]-=mat.num[i][k]*1ll*mat.num[j][i]%mod*tmp%mod,
  49. mat.num[j][k]+=mat.num[j][k]<?mod:;
  50. }
  51. for (int i=;i<=K;i++) ans=1ll*ans*mat.num[i][i]%mod;
  52. return ans;
  53. }
  54.  
  55. int vis[maxn][maxn],Time; bool die;
  56. void dfs(int x,int y)
  57. {
  58. if (mp[x][y]=='.') return;
  59. if (vis[x][y])
  60. {
  61. if (pos[x][y]==-) die=;
  62. return;
  63. }
  64. vis[x][y]=;
  65. int tx=x,ty=y;
  66. if (mp[x][y]=='U') x--;
  67. else if (mp[x][y]=='D') x++;
  68. else if (mp[x][y]=='L') y--;
  69. else if (mp[x][y]=='R') y++;
  70. if (x< || x>n || y< || y>m) pos[tx][ty]=;
  71. else pos[tx][ty]=-,dfs(x,y),pos[tx][ty]=pos[x][y];
  72. }
  73. int check(int x,int y)
  74. {
  75. if (x< || x>n || y< || y>m) return ;
  76. return pos[x][y];
  77. }
  78.  
  79. int main()
  80. {
  81. scanf("%d",&T);
  82. while (T--)
  83. {
  84. scanf("%d%d",&n,&m); K=; Time=; die=;
  85. memset(vis,,sizeof(vis));
  86. memset(pos,,sizeof(pos));
  87. for (int i=;i<=n;i++) scanf("%s",mp[i]+);
  88. for (int i=;i<=n;i++)
  89. for (int j=;j<=m;j++)
  90. if (mp[i][j]=='.') pos[i][j]=++K;
  91. for (int i=;i<=n;i++)
  92. for (int j=;j<=m;j++)
  93. if (mp[i][j]!='.') dfs(i,j);
  94. if (die) {puts(""); continue;}
  95.  
  96. for (int i=;i<=n;i++)
  97. for (int j=;j<=m;j++)
  98. if (mp[i][j]=='.')
  99. {
  100. int nx=i,ny=j,now=pos[i][j];
  101. nx++; place[now][]=check(nx,ny); nx--;
  102. nx--; place[now][]=check(nx,ny); nx++;
  103. ny++; place[now][]=check(nx,ny); ny--;
  104. ny--; place[now][]=check(nx,ny); ny++;
  105. }
  106. mat.clear();
  107. for (int i=;i<=K;i++)
  108. {
  109. for (int j=;j<;j++) mat.num[place[i][j]][i]--;
  110. mat.num[i][i]+=;
  111. }
  112. for (int i=;i<=K;i++)
  113. for (int j=;j<=K;j++)
  114. if (mat.num[i][j]<) mat.num[i][j]+=mod;
  115. printf("%d\n",gauss());
  116. }
  117. return ;
  118. }

走进矩阵树定理--「CodePlus 2017 12 月赛」白金元首与独舞的更多相关文章

  1. [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞

    [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞 试题描述 到河北省 见斯大林 / 在月光下 你的背影 / 让我们一起跳舞吧 うそだよ~ 河北省怎么可能有 Stalin. ...

  2. 【LibreOJ】#6259. 「CodePlus 2017 12 月赛」白金元首与独舞

    [题目]给定n行m列的矩阵,每个位置有一个指示方向(上下左右)或没有指示方向(任意选择),要求给未定格(没有指示方向的位置)确定方向,使得从任意一个开始走都可以都出矩阵,求方案数.n,m<=20 ...

  3. 「CodePlus 2017 12 月赛」白金元首与独舞

    description 题面 data range \[ 1 \leq T \leq 10, 1 \leq n, m \leq 200 , 0 \leq k \leq \min(nm, 300)\] ...

  4. loj6259「CodePlus 2017 12 月赛」白金元首与独舞

    分析 我们将没连的点连向周围四个点 其余的按照给定的方向连 我们将所有连出去的位置统一连到0点上 再以0作为树根 于是就将问题转化为了有向图内向树计数 代码 #include<iostream& ...

  5. 「CodePlus 2017 12 月赛」火锅盛宴(模拟+树状数组)

    1A,拿来练手的好题 用一个优先队列按煮熟时间从小到大排序,被煮熟了就弹出来. 用n个vector维护每种食物的煮熟时间,显然是有序的. 用树状数组维护每种煮熟食物的数量. 每次操作前把优先队列里煮熟 ...

  6. 「CodePlus 2017 12 月赛」可做题2(矩阵快速幂+exgcd+二分)

    昨天这题死活调不出来结果是一个地方没取模,凉凉. 首先有个一眼就能看出来的规律... 斐波那契数列满足$a_1, a_2, a_1+a_2, a_1+2a_2, 2a_1+3a_2, 3a_1+5a_ ...

  7. 【LibreOJ】#6257. 「CodePlus 2017 12 月赛」可做题2

    [题意]数列满足an=an-1+an-2,n>=3.现在a1=i,a2=[l,r],要求满足ak%p=m的整数a2有多少个.10^18. [算法]数论(扩欧)+矩阵快速幂 [题解]定义fib(i ...

  8. 【LIbreOJ】#6256. 「CodePlus 2017 12 月赛」可做题1

    [题意]定义一个n阶正方形矩阵为“巧妙的”当且仅当:任意选择其中n个不同行列的数字之和相同. 给定n*m的矩阵,T次询问以(x,y)为左上角的k阶矩阵是否巧妙.n,m<=500,T<=10 ...

  9. 「CodePlus 2017 12 月赛」火锅盛宴

    n<=100000种食物,给每个食物煮熟时间,有q<=500000个操作:在某时刻插入某个食物:查询熟食中编号最小的并删除之:查询是否有编号为id的食物,如果有查询是否有编号为id的熟食, ...

随机推荐

  1. ASP.NET中调用事务处理的方法

    /// <summary> /// 事务处理 /// </summary> /// <param name="strSql"></para ...

  2. Java线程-线程的基本状态

    问题:线程有哪些基本状态?这些状态是如何定义的? 新建(new):新创建了一个线程对象. 可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法.该状 ...

  3. SQL转Java代码小工具

    工作中使用SQL的时候很多,当使用hibernate的时候,经常遇到多行的SQL,通常在PL/SQL或其他地方写好SQL,测试没问题后,需要将SQL写到程序代码中,多行SQL需要拼接字符串,手动一行行 ...

  4. 关于mapState和mapMutations和mapGetters 和mapActions辅助函数的用法及作用(二)-----mapMutations

    在组件中提交Mutations: import { mapState, mapMutations } from 'vuex' export default { data() { return { ms ...

  5. Android(java)学习笔记193:ContentProvider使用之获得系统联系人信息01

    1.系统联系人的数据库(3张最重要的表) (1)raw_contacts  联系人表        保存联系人的id   contact_id (2)data 数据表       保存联系人的数据 ( ...

  6. hibernate inverse属性

    修改街道对应的区道信息: 修改后会发现程序执行了两次修改操作: 原因: 区道与街道是一对多的关系: 由于Hibernate是双向维护外键,所以当修改区道中的街道时,会修改一次外键:在修改街道中的区道时 ...

  7. Webpack 入门(一):安装 / 打包 / 命令行

    一:安装webpack和基本环境搭建 新建一个工作的文件夹(我取的名字叫Webpack) 打开命令行,cd进入该文件夹 //初始化一下npm > E:\work\Webpack>npm i ...

  8. CS2QS

    inline QString MotorCS2QS(CString cs) { return QString::fromWCharArray((LPCTSTR)cs, cs.GetLength()); ...

  9. CAD参数绘制多段线(网页版)

    多段线又被称为多义线,表示一起画的都是连在一起的一个复合对象,可以是直线也可以是圆弧并且它们还可以加不同的宽度. 主要用到函数说明: _DMxDrawX::PathLineTo 把路径下一个点移到指定 ...

  10. E. String Multiplication

    E. String Multiplication time limit per test 2 seconds memory limit per test 256 megabytes input sta ...