1 条题解
-
0
自动搬运
来自洛谷,原作者为

SSerxhs
我仍然在/无人问津的阴雨霉湿之地/和着雨音/唱着没有听众的歌曲搬运于
2025-08-24 22:32:37,当前版本为作者最后更新于2021-07-26 15:56:18,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
先考虑 的情况.容易发现一条路径(或称为一组匹配) 对应一个排列 ,那么两条边 有交点等价于 ,这说明交点个数等于逆序对数.由于待求的是交点个数为偶数的减去交点个数为奇数的,容易联想到行列式.因此 时答案即为邻接矩阵行列式的值.
对于 但 的情况,注意到一个结论:设 表示第 层和第 层交点数为偶数的方案数, 表示第 层和第 层交点数为奇数的方案数,有 $(f_i-g_i)(f_{i+1}-g_{i+1})=(f_if_{i+1}+g_ig_{i+1})-(f_ig_{i+1}+g_if_{i+1})$,可以发现正好是第 层到第 层的答案(因为偶数依然是正的,奇数依然是负的).这表明答案即为每层邻接矩阵对应行列式的乘积.
对于一般情况,考虑类似思路合并相邻两层.容易想到将邻接矩阵相乘即可计算第 层到第 层的邻接矩阵.可以画图证明,将两条边缩为一条边后,交点奇偶性不变.故答案即为邻接矩阵依次相乘后所得 矩阵的行列式.从 以及上一做法结合结论 可以看出这一结论十分自然.
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)); } }
- 1
信息
- ID
- 7111
- 时间
- 1000ms
- 内存
- 1024MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者