zoukankan      html  css  js  c++  java
  • [NOI 2021] 路径交点

    题目

    传送门

    解法

    首先考虑 (k=2) 的情况。这相当于枚举全排列 (p),每种排列的逆序对数就是交点数。令 ( au(p)) 是某排列逆序对数,(g) 是邻接矩阵,将其公式化就是:

    [ ext{Ans}=sum_{p}(-1)^{ au(p)}prod_{i=1}^n g_{i,p_i} ]

    这不就是 (g) 的行列式吗?这个可以用高斯消元 (mathcal O(n^3)) 求出。

    对于 (k=3)(n_1=n_2=n_3) 的情况。我们发现,它的答案就是 (g_1,g_2) 行列式的乘积。设 (f_{i,0/1})(i)(i+1) 层交点个数为偶/奇的方案数。那么有:

    [ ext{det}(g_1) ext{det}(g_2)=(f_{1,0}-f_{1,1})(f_{2,0}-f_{2,1}) ]

    [=(f_{1,0}f_{2,0}+f_{1,1}f_{2,1})-(f_{1,0}f_{2,1}+f_{1,1}f_{2,0}) ]

    其它情况可以归纳证明。

    但是 (n_i) 并没有那么理想。还是考虑 (k=3)(n_1=n_3< n_2) 的情况。我们可以枚举第 (2) 层选了哪 (n_1) 个点,再按照之前的方法计算。这时就要引出一个公式 ——

    ( ext{Binet-Cauchy}) 公式:

    (A=(a_{i,j})_{n imes m},B=(b_{i,j})_{m imes n})

    • (n>m)。就有 ( ext{det}(AB)=0)

      ( ext{rank}(AB)le ext{rank}(A)le m<n)。所以矩阵 (AB) 不满秩。

    • (nle m)(AB) 的行列式等于 (A) 的所有 (n) 阶子式以及 (B) 相应 (n) 阶子式乘积之和。

    题目中保证 (nle m),于是我们可以直接用此公式。也即所有邻接矩阵的乘积的行列式就是答案。

    你还可以用另一种方式理解这个答案。

    注意到,答案只和第 (1) 层到达第 (k) 层的邻接矩阵有关。因为初末相对位置决定了路径 (i) 是否会穿过路径 (j)(我们认为穿过去再穿回来是无效的)。

    不过还有个问题:不论是用公式还是以上文的理解,我们都没有考虑 每个顶点至多出现在一条路径中 的要求。事实上,假设第 (1) 层的 (i,j) 都经过了某层的点 (o),在 (o) 之后 (i,j) 的可选方案实际上是一样的。若 (i) 最终到达第 (n) 层的 (i')(j) 到了 (j'),它可以和 (i)(j')(j)(i') 的情况相互抵消(逆序对数只变化 (1)),而这些情况可以两两配对,所以对答案没有影响。

    总时间复杂度应该是 (mathcal O(n^3kT)) 的。

    再提一嘴

    如果直接计算路径方案数就是积和式,它的计算需要 (mathcal O(n!))。所以加上这个 (mathtt{qqgg}) 的奇偶限制题目变简单了。

    代码

    #include <cstdio>
    
    #define print(x,y) write(x),putchar(y)
    
    template <class T> inline T read(const T sample) {
    	T x=0; char s; bool f=0;
    	while((s=getchar())>'9' or s<'0')
    		f|=(s=='-');
    	while(s>='0' and s<='9')
    		x=(x<<1)+(x<<3)+(s^48),
    		s=getchar();
    	return f?-x:x;
    }
    
    template <class T> inline void write(const T x) {
    	if(x<0) return (void)(putchar('-'),write(-x));
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    } 
    
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    const int mod=998244353,maxk=105;
    
    inline int inc(const int x,const int y) {
    	return x+y>=mod?x+y-mod:x+y;
    }
    
    int inv(int x,int y=mod-2) {
    	int r=1;
    	while(y) {
    		if(y&1) r=1ll*r*x%mod;
    		x=1ll*x*x%mod; y>>=1;
    	}
    	return r;
    }
    
    int k,n[maxk],m[maxk]; 
    struct mat {
    	int a[maxk<<1][maxk<<1],n,m;
    	mat operator * (const mat &t) const {
    		mat r; r.n=n,r.m=t.m;
    		memset(r.a,0,sizeof r.a);
    		for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			if(a[i][j])
    				for(int k=1;k<=r.m;++k)
    					r.a[i][k]=inc(
    						r.a[i][k],
    						1ll*a[i][j]*t.a[j][k]%mod
    					);
    		return r;
    	}
    	void Clear() {
    		for(int i=1;i<=n;++i)
    			for(int j=1;j<=m;++j)
    				a[i][j]=0;
    	}
    	int Gauss() {
    		int j,tmp,r=1; bool f=0;
    		for(int i=1;i<=n;++i) {
    			for(j=i;j<=n;++j)
    				if(a[j][i]) break;
    			if(j>n) return 0;
    			if(i^j) swap(a[i],a[j]),f^=1;
    			r=1ll*r*a[i][i]%mod;
    			tmp=inv(a[i][i]);
    			for(j=i;j<=n;++j)
    				a[i][j]=1ll*a[i][j]*tmp%mod;
    			for(j=i+1;j<=n;++j) {
    				a[j][i]=mod-a[j][i];
    				for(int k=i+1;k<=n;++k)
    					a[j][k]=inc(a[j][k],1ll*a[j][i]*a[i][k]%mod);
    				a[j][i]=0;
    			}
    		}
    		return f?mod-r:r;
    	}
    } A,B,C;
    
    signed main() {
    	int u,v;
    	for(int T=read(9);T;--T) {
    		k=read(9);
    		for(int i=1;i<=k;++i)
    			n[i]=read(9);
    		for(int i=1;i<k;++i)
    			m[i]=read(9);
    		A.n=n[1],A.m=n[2];
    		for(int i=1;i<=m[1];++i) {
    			u=read(9),v=read(9);
    			A.a[u][v]=1;
    		}
    		for(int i=2;i<k;++i) {
    			B.n=n[i],B.m=n[i+1];
    			for(int j=1;j<=m[i];++j) {
    				u=read(9),v=read(9);
    				B.a[u][v]=1;
    			}
    			C=A*B;
    			A=C,B.Clear();
    		}
    		print(A.Gauss(),'
    '); A.Clear();
    	}
    	return 0;
    }
    
  • 相关阅读:
    LOJ P10004 智力大冲浪 题解
    LOJ P10011 愤怒的牛 题解
    LOJ P10002 喷水装置 题解
    洛谷 P2279 [HNOI2003]消防局的设立 题解
    洛谷 P5640 【CSGRound2】逐梦者的初心 题解
    洛谷 P2827 蚯蚓 题解
    [SHOI2012]魔法树
    浅析树链剖分
    [Bzoj1731]排队布局
    [POJ-1201]Intervals
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/15065175.html
Copyright © 2011-2022 走看看