LGV引理

看着格路计数看着看着就到这了。

LGV引理

LGV引理拿来求DAG图上不相交路径计数等问题(事实上在不是平面图的DAG上会有若干问题,一会再说)。

然后是引理内容。首先是一大堆定义。

\(\omega(P)\)\(P\) 这条路径上所有边的边权乘积。一般都是 \(1\) ,拿来路径计数。(据说只要边权在交换环上都可以,比如生成函数)。

\(e(u,v)\)\(u\rightarrow v\) 的每条路径 \(P\)\(\omega(P)\) 之和。

一组 \(A\rightarrow B\) 的不相交路径 \(S\)\(S_i\) 是一条从 \(A_i\)\(B_{\sigma(i)}\) 的路径( \(\sigma(i)\) 是一个排列),满足 \(\forall i\neq j\)\(S_i,S_j\) 没有公共顶点。

\(N(\sigma)\) 表示排列 \(\sigma\) 的逆序对个数。

然后终于到了引理内容。设矩阵

\[M= \begin{pmatrix} e(A_1,B_1) & e(A_1,B_2) & \cdots & e(A_1,B_n)\\ e(A_2,B_1) & e(A_2,B_2) & \cdots & e(A_2,B_n)\\ &\vdots&&\\ e(A_n,B_1) & e(A_n,B_2) & \cdots & e(A_n,B_n)\\ \end{pmatrix} \]

那么所有从 \(A\)\(B\) 的不相交路径的带符号和

\[\sum_S(-1)^{N(\sigma(S))}\prod_{i=1}^n\omega(S_i) \]

的值为 \(\det(M)\)

证明不会。直接上题。

P6657 【模板】LGV引理

题意: \(m\) 个棋子,第 \(i\) 个要从 \((a_i,1)\) 走到 \((b_i,n)\) ,求所有棋子路径不相交的方案数\(\mod 998244353\)

首先按照套路直接把所有 \(\omega\) 看成 \(1\) ,然后 \(e(i,j)\) 就是从 \((a_i,1)\) 走到 \((b_j,n)\) 的路径条数,显然是 \(\binom{b_j-a_i+n-1}{n-1}\) 。直接求行列式即可。

这东西上代码我怕不是有什么大病。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
const int mod=998244353;
int n,m,a[110][110],jc[2000010],inv[2000010],A[110],B[110];
int qpow(int a,int b){
	int ans=1;
	while(b){
		if(b&1)ans=1ll*ans*a%mod;
		a=1ll*a*a%mod;
		b>>=1;
	}
	return ans;
}
int C(int n,int m){
	if(n<m)return 0;
	return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}
int gauss(int n){
    int ans=1,w=1;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			while(a[i][i]){
				int rate=a[j][i]/a[i][i];
				for(int k=i;k<=n;k++){
					a[j][k]=(a[j][k]-1ll*rate*a[i][k]%mod+mod)%mod;
				}
				for(int k=1;k<=n;k++)swap(a[i][k],a[j][k]);
				w=-w;
			}
			for(int k=1;k<=n;k++)swap(a[i][k],a[j][k]);
			w=-w;
		}
	}
	for(int i=1;i<=n;i++)ans=1ll*ans*a[i][i]%mod;
	ans=(1ll*ans*w%mod+mod)%mod;
	return ans;
}
signed main(){
	int tim;scanf("%d",&tim);jc[0]=inv[0]=1;
	for(int i=1;i<=2000000;i++)jc[i]=1ll*jc[i-1]*i%mod;
	inv[2000000]=qpow(jc[2000000],mod-2);
	for(int i=1999999;i>=1;i--)inv[i]=1ll*inv[i+1]*(i+1)%mod;
	while(tim--){
		scanf("%d%d",&n,&m);
		for(int i=1;i<=m;i++)scanf("%d%d",&A[i],&B[i]);
		for(int i=1;i<=m;i++){
			for(int j=1;j<=m;j++){
				a[i][j]=C(B[j]-A[i]+n-1,n-1);
			}
		}
		printf("%d\n",gauss(m));
	}
	return 0;
}

CF248D Turtle

题意:网格图一些点不能走,两个点从 \((1,1)\) 走到 \((n,m)\) ,求不相交路径数 \(\mod 1000000007\) 。(他的 \((1,1)\) 是左上角 \((n,m)\) 是右下角)

首先显然第一步必须一个往右一个往下。然后如果不相交显然往右的必须到 \((n-1,m)\) ,往下的必须到 \((n,m-1)\) 。所以这玩意就变成了普及组 \(dp\) 外加一个二阶行列式,爆算即可。

然后让我蒯一点jijidawang的博客里的题。

ABC216H

题意: \(K\) 个机器人,每个初始位置为 \(x_i\) ,现在所有机器人同时走 \(n\) 步,每步有 \(\frac 12\)的概率向右或不动,求没有机器人相遇的方案数。 \(n,x\le 1000,K\le 10\)
首先转化成二维网格上的问题。不动就是向上走,向右就是向右上。所以最后一定会向上 \(n\) 步。

然后我们发现 \(n\) 大的要命没法大力枚举在哪里停住然后硬上LGV引理。

所以看 \(K\) 比较小,考虑状压。设 \(dp[s][j]\)\(s\) 集合内最右边的点位置 \(\le j\) 的带权方案数,那么每次考虑加进来一个点,显然有

\[dp[s][j]=dp[s][j-1]+\sum_{i\in s}(-1)^{\sum_{j\in s}[i<j]}dp[s-i][j-1]\binom{n}{j-x_i} \]

然后是我们开头的那句话:“在不是平面图的DAG上会有若干问题”。来看看会有哪些问题。

NOI2021D1T2 路径交点

经过感性理解我们可以提出:中间的点其实没有影响,交点的奇偶只与从起点到终点的路径组的逆序对的奇偶有关。也就是说我们直接求所有路径组的带方向权值和,直接上LGV引理就行。

为什么这个题可以直接上LGV引理呢?发现别的题中符合要求的匹配只有一组,因此按照匹配的顺序列矩阵求出的就是不交路径数量。但是这个题有最多 \(n!\) 组匹配,所以这时直接上就不是原本的权值和,而是带方向(逆序对偶数为正,奇数为负)的权值和。而这个题正好需要带方向的权值和,所以可以直接上。

路径数量可以直接大力BFS求出,不再说明。

posted @ 2022-10-09 17:55  gtm1514  阅读(88)  评论(0编辑  收藏  举报