正题
题目链接:https://www.luogu.com.cn/problem/P7736
题目大意
有kkk层的图,第iii层有nin_ini个点,每层的点从上到下排列,层从左到右排列。再给出连接相邻层的一些有向边(从iii层连向i+1i+1i+1层)。
对于n1n_1n1层每个点作为起点同时出发走到不同的nkn_knk层的点的所有路径方案中,交点数量为偶数的减去为奇数的方案有多少个。
1≤k≤100,2≤n1≤100,n1=nk,n1≤ni≤2×n1,1≤T≤51\leq k\leq 100,2\leq n_1\leq 100,n_1=n_k,n_1\leq n_i\leq 2\times n_1,1\leq T\leq 51≤k≤100,2≤n1≤100,n1=nk,n1≤ni≤2×n1,1≤T≤5
解题思路
分析一下,若第111层起点1,21,21,2分别对应终点1,21,21,2,记fi,1/2f_{i,1/2}fi,1/2表示1/21/21/2在第iii层的位置。中间某个位置他们路径有了交点,那么一定满足他们存在一层使得fi,1>fi,2f_{i,1}>f_{i,2}fi,1>fi,2但是因为f1,1<f1,2f_{1,1}<f_{1,2}f1,1<f1,2且fn,1<fn,2f_{n,1}<f_{n,2}fn,1<fn,2也就是说明前后都各有一个交点。
拓展一下也就是说中间的路径走法不影响交点的奇偶性,只有起点和终点会影响奇偶性。再进一步说,路径交点的奇偶性就是起点对应终点的排列pip_ipi的逆序对数量的奇偶性。
设排列ppp表示起点iii会走到终点pip_ipi,σ(p)\sigma(p)σ(p)表示排列ppp的逆序对数量,w(p)w(p)w(p)表示排列ppp的路径方案
那么答案就是
∑(−1)σ(p)w(p)\sum (-1)^{\sigma(p)}w(p)∑(−1)σ(p)w(p)
发现和LGVLGVLGV引理的式子一模一样,直接上就好了
时间复杂度O(T(k2n+n3))O(T(k^2n+n^3))O(T(k2n+n3))
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<vector>
#define ll long long
using namespace std;
const ll N=210,P=998244353;
ll T,k,n[N],m[N],f[N][N],a[N][N];
vector<int> G[N][N];
ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
ll power(ll x,ll b){ll ans=1;while(b){if(b&1)ans=ans*x%P;x=x*x%P;b>>=1;}return ans;
}
ll det(ll n){ll ans=1,f=1;for(ll i=1;i<=n;i++){for(ll j=i;j<=n;j++)if(a[j][i]){if(j!=i)swap(a[j],a[i]),f=!f;break;}ll inv=power(a[i][i],P-2);ans=ans*a[i][i]%P;for(ll j=i;j<=n;j++)a[i][j]=a[i][j]*inv%P;for(ll j=i+1;j<=n;j++){ll rate=P-a[j][i];for(ll k=i;k<=n;k++)(a[j][k]+=rate*a[i][k]%P)%=P;}}return f?ans:((P-ans)%P);
}
signed main()
{T=read();while(T--){k=read();for(ll i=1;i<=k;i++)n[i]=read();for(ll i=1;i<k;i++)m[i]=read();for(ll i=1;i<k;i++){for(ll j=1;j<=m[i];j++){ll x=read(),y=read();G[i][x].push_back(y);}}for(ll i=1;i<=n[k];i++){f[k][i]=1;f[k][i-1]=0;for(ll j=k-1;j>=1;j--)for(ll x=1;x<=n[j];x++){f[j][x]=0;for(ll p=0;p<G[j][x].size();p++)(f[j][x]+=f[j+1][G[j][x][p]])%=P;}for(ll j=1;j<=n[1];j++)a[j][i]=f[1][j];}f[k][n[k]]=0;printf("%lld\n",det(n[1]));for(ll i=1;i<=k;i++)for(ll j=1;j<=n[i];j++)G[i][j].clear();}return 0;
}