LGV 引理学习笔记

NOI2021D1T2 是 LGV 板板题,震撼。

ABC216H Random Robots

考虑转化题意:有 (k) 个起点 ((x_1,0),(x_2,0),cdots,(x_k,0))(n) 轮,每轮所有位置 ((x,y)) 都会等概率走到 ((x+1,y+1))((x,y+1)),求路径不相交的概率。(显然等价于方案数)

这个东西明示我们使用 LGV 引理,考虑 dp 求解,设 (f(S,t)) 为考虑集合 (S),终点的 (x) 最大值为 (t) 的答案:

[f(S,t)=sum_{0leqslant y_1<y_2<cdots<y_{|S|}leqslant t}left|egin{matrix}w(x_{S_1},y_1)&w(x_{S_1},y_2)&cdots&w(x_{S_1},y_{|S|})\w(x_{S_2},y_1)&w(x_{S_2},y_2)&cdots&w(x_{S_2},y_{|S|})\vdots&vdots&ddots&vdots\w(x_{|S|},y_1)&w(x_{|S|},y_2)&cdots&w(x_{|S|},y_{|S|})end{matrix} ight| ]

其中 (w(x,y)={nchoose y-x})

(y_k<t)

[f(S,t)leftarrow f(S,t-1) ]

(y_k=t)

[f(S,t)leftarrowsum_{i=1}^{|S|}(-1)^{|S|+i}w(x_{S_i},t)f(S-{S_i},t-1) ]

然后直接状压 dp 即可,时间复杂度:(O(2^kk(n+max{x_i})))

#include<stdio.h>
const int maxk=1<<10,maxn=2005,mod=998244353,inv2=(mod+1)/2;
int n,k,ans,mulinv2;
int x[maxn],bitcnt[maxk],f[maxk][maxn],C[maxn][maxn],mul[2];
int main(){
	scanf("%d%d",&k,&n);
	for(int i=1;i<=k;i++)
		scanf("%d",&x[i]);
	mul[0]=1,mul[1]=mod-1;
	for(int i=0;i<=n;i++){
		C[i][0]=C[i][i]=1;
		for(int j=1;j<i;j++)
			C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
	}
	mulinv2=1;
	for(int i=1;i<=n;i++)
		mulinv2=1ll*mulinv2*inv2%mod;
	for(int i=1;i<(1<<k);i++)
		bitcnt[i]=bitcnt[i>>1]+(i&1);
	f[0][0]=1;
	for(int i=0;i<=x[k]+n;i++){
		for(int j=0;j<(1<<k);j++)
			f[i+1][j]=f[i][j];
		for(int j=0;j<(1<<k);j++)
			for(int p=1;p<=k;p++)
				if(((j>>(p-1))&1)==0&&x[p]<=i&&i-x[p]<=n)
					f[i+1][j|(1<<(p-1))]=(f[i+1][j|(1<<(p-1))]+1ll*f[i][j]*mul[bitcnt[j>>(p-1)]&1]%mod*C[n][i-x[p]]%mod*mulinv2)%mod;
	}
	printf("%d
",f[x[k]+n+1][(1<<k)-1]);
	return 0;
}
原文地址:https://www.cnblogs.com/xiaoziyao/p/15253693.html