把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【CF348D】Turtles(LGV引理)

点此看题面

  • 给定一张\(n\times m\)的网格图,其中有一些障碍格子。
  • 求有多少条从\((1,1)\)\((n,m)\)的路径,满足除起点和终点外不相交。
  • \(n,m\le3000\)

\(LGV\)引理

一开始智障了,直接无脑套公式,求出\((1,1)\)\((n,m)\)的方案数\(f_{n,m}\)然后认为答案就是:

\[\det\begin{bmatrix}f_{n,m}&f_{n,m}\\f_{n,m}&f_{n,m}\end{bmatrix} \]

然后仔细一想不太对劲,众所周知二阶行列式\(\det\begin{bmatrix}a&b\\c&d\end{bmatrix}=ad-bc\),那么上面的式子算出来就是\(0\)

是公式出了问题?显然不是。

\(LGV\)引理要求的不相交是包括起点和终点的,起点和终点相同则肯定相交,因此方案数就是我们算出来的\(0\)

所以,我们要让它们开始先各走一步,最后各少走一步,也就是分别从\((1,2)\)走到\((n,m-1)\),从\((2,1)\)走到\((n-1,m)\)

于是设\(f1_{i,j},f2_{i,j}\)分别表示从\((1,2),(2,1)\)走到\((i,j)\)的方案数,转移的话如果当前格子是障碍就为\(0\),否则就是\(f_{i,j-1}+f_{i-1,j}\)

最终答案就是\(\det\begin{bmatrix}f1_{n-1,m}&f1_{n,m-1}\\f2_{n-1,m}&f2_{n,m-1}\end{bmatrix}\),直接算就好了。

代码:\(O(nm)\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 3000
#define X 1000000007
using namespace std;
int n,m,f1[N+5][N+5],f2[N+5][N+5];char s[N+5][N+5];
int main()
{
	RI i,j;for(scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%s",s[i]+1);
	for(i=1;i<=n;++i) for(j=1;j<=m;++j) s[i][j]^'#'&&//是障碍则方案数为0
		(f1[i][j]=i==1&&j==2?1:(f1[i-1][j]+f1[i][j-1])%X,f2[i][j]=i==2&&j==1?1:(f2[i-1][j]+f2[i][j-1])%X);//求出(1,2),(2,1)到每个格子的方案数
	return printf("%d\n",(1LL*f1[n-1][m]*f2[n][m-1]-1LL*f1[n][m-1]*f2[n-1][m]%X+X)%X),0;//二阶行列式直接计算
}
posted @ 2021-05-19 15:58  TheLostWeak  阅读(95)  评论(0)    收藏  举报