题解 P7736 【[NOI2021] 路径交点】
先考虑
对于
对于一般情况,考虑类似思路合并相邻两层.容易想到将邻接矩阵相乘即可计算第
int cal(int a[][N],register int n)
{
register int i,j,k,r=1,fh=0,l;
for (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[j],a[i]);fh^=1;}
r=(ll)r*a[i][i]%p;
k=ksm(a[i][i],p-2);
for (j=i;j<=n;j++) a[i][j]=(ll)a[i][j]*k%p;
for (j=i+1;j<=n;j++)
{
a[j][i]=p-a[j][i];
for (k=i+1;k<=n;k++) a[j][k]=(a[j][k]+(ll)a[j][i]*a[i][k])%p;
a[j][i]=0;
}
}
if (fh) return (p-r)%p;
return r;
}
char s[N];
int a[N][N],c[N][N],d[N][N],b[N],f[N];
int T,n,m,i,j,k,x,y,z,ans,la,ksiz,ks;
void mul(int n,int m,int l)
{
int i,j,k;
for (i=1;i<=n;i++) for (j=1;j<=l;j++) d[i][j]=0;
for (i=1;i<=n;i++) for (k=1;k<=m;k++) for (j=1;j<=l;j++) d[i][j]=(d[i][j]+(ll)a[i][k]*c[k][j])%p;
for (i=1;i<=n;i++) for (j=1;j<=m;j++) a[i][j]=0;
for (i=1;i<=m;i++) for (j=1;j<=l;j++) c[i][j]=0;
for (i=1;i<=n;i++) for (j=1;j<=l;j++) a[i][j]=d[i][j];
}
int main()
{
read(T);
while (T--)
{
read(k);
for (i=1;i<=k;i++) read(b[i]);
for (i=1;i<k;i++) if (b[i]!=b[i+1]) break;
memset(a,0,sizeof a);
memset(c,0,sizeof c);
read(f,k-1);m=f[1];
while (m--) read(x,y),a[x][y]=1;n=b[1];
for (i=2;i<k;i++)
{
m=f[i];
while (m--) read(x,y),c[x][y]=1;
mul(n,b[i],b[i+1]);
}
enter(cal(a,n));
}
}