[loj3626]愚蠢的在线法官
交换$a_{x}$和$a_{y}$会同时交换行列式的两行和两列,不改变行列式的值,不妨将$a_{i}$按照dfs序排序
此时,$k$子树内的$a_{i}$构成连续区间,设其为区间$[l_{k},r_{k}]$,并记录$a_{[l_{k},r_{k}]}$所对应的行列式
考虑转移,将$[l_{k},r_{k}]$按照$k$和不同的子树划分为若干段,前者可以直接处理,后者递归子树处理
考虑合并,问题即求$\det \left(\begin{array}{ll}A&B\\C&D\end{array}\right)$(已知$\det A,D$且$B,C$中所有元素均为$v_{k}$)
记$A_{t}$为将$A$中所有元素减去$t$所得到的行列式,将其代入行列式的式子,不难得到
$$
\begin{array}{ll}\det A_{t}&=\sum_{P}(-1)^{inv(P)}\prod_{i=1}^{n}(A_{i,P_{i}}-t)\\&=\sum_{P}(-1)^{inv(P)}\sum_{S\subseteq [1,n]}(-t)^{|S|}\prod_{x\not\in S}A_{x,P_{x}}\\&=\sum_{S\subseteq [1,n]}(-t)^{|S|}\sum_{P}(-1)^{inv(P)}\prod_{x\not\in S}A_{x,P_{x}}\end{array}
$$
对于最后一项,当$|S|\ge 2$时,任取$x,y\in S$,交换$P_{x}$和$P_{y}$后即相互抵消,因此后者为0
当$|S|<2$时,对$S=\empty$和$S=\{i\}$分别处理,即
$$
\det A_{t}=\det A-t\sum_{i=1}^{n}\sum_{P}(-1)^{inv(P)}\prod_{x\ne i}A_{x,P_{x}}
$$
记后者为$\det_{s}A$,即将任意一行所有元素均变为1后的行列式之和,将其与$\det A$一起维护
同时,对其分别做以下两个变形:1.移项;2.代入$A=A_{t_{-t}}$,即
$$
\begin{cases}\det A=\det A_{t}+t\det_{s}A\\\det A=\det A_{t}+t\det_{s}A_{t}\end{cases}
$$
两式相减,即解得$\det_{s}A=\det_{s}A_{t}$(通俗的来说,即所有元素同时加上一个值后不改变$\det_{s}$)
综上,即得到转移为
$$
\begin{array}{ll}\det_{s}\left(\begin{array}{ll}A&B\\C&D\end{array}\right)&=\det_{s}\left(\begin{array}{ll}A&B\\C&D\end{array}\right)_{v_{k}}=\det_{s}\left(\begin{array}{ll}A_{v_{k}}&O\\O&D_{v_{k}}\end{array}\right)\\&=\det_{s}A \times \det D_{v_{k}}+\det A_{v_{k}}\times \det_{s}D\\&=\det_{s}A\times (\det D-v_{k}\det_{s}D)+(\det A-v_{k}\det_{s}A)\det_{s}D\end{array}
$$
$$
\begin{array}{ll}\det \left(\begin{array}{ll}A&B\\C&D\end{array}\right)&=\det \left(\begin{array}{ll}A&B\\C&D\end{array}\right)_{v_{k}}+v_{k}\det_{s}\left(\begin{array}{ll}A&B\\C&D\end{array}\right)\\&=\det A_{v_{k}}\times \det D_{v_{k}}+v_{k}\det_{s}\left(\begin{array}{ll}A&B\\C&D\end{array}\right)\\&=(\det A-v_{k}\det_{s}A)(\det D-v_{k}\det_{s}D)+v_{k} \det_{s}\left(\begin{array}{ll}A&B\\C&D\end{array}\right)\end{array}
$$
时间复杂度为$o(n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 500005 4 #define mod 998244353 5 #define ll long long 6 vector<int>e[N]; 7 int n,m,x,y,v[N],cnt[N],vis[N],g[N],f[N]; 8 void dfs(int k,int fa){ 9 vis[k]=f[k]=g[k]=0; 10 if (cnt[k])vis[k]=1,f[k]=v[k],g[k]=1; 11 for(int i=0;i<e[k].size();i++) 12 if (e[k][i]!=fa){ 13 dfs(e[k][i],k); 14 if (!vis[e[k][i]])continue; 15 if (!vis[k])vis[k]=1,f[k]=f[e[k][i]],g[k]=g[e[k][i]]; 16 else{ 17 int s1=(f[k]-(ll)v[k]*g[k]%mod+mod)%mod; 18 int s2=(f[e[k][i]]-(ll)v[k]*g[e[k][i]]%mod+mod)%mod; 19 int gg=((ll)g[k]*s2+(ll)g[e[k][i]]*s1)%mod; 20 f[k]=((ll)s1*s2+(ll)v[k]*gg)%mod,g[k]=gg; 21 } 22 } 23 } 24 int main(){ 25 scanf("%d%d",&n,&m); 26 for(int i=1;i<=n;i++)scanf("%d",&v[i]); 27 for(int i=1;i<=m;i++){ 28 scanf("%d",&x); 29 cnt[x]++; 30 } 31 for(int i=1;i<n;i++){ 32 scanf("%d%d",&x,&y); 33 e[x].push_back(y),e[y].push_back(x); 34 } 35 for(int i=1;i<=n;i++) 36 if (cnt[i]>1){ 37 printf("0\n"); 38 return 0; 39 } 40 dfs(1,0); 41 printf("%d\n",f[1]); 42 return 0; 43 }