• [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 }
    View Code
  • 相关阅读:
    [BZOJ 1295][SCOI2009]最长距离(SPFA+暴力)
    [BZOJ 3143][HNOI2013]游走(数学期望)
    [BZOJ 1797][AHOI2009]最小割(最小割关键边的判断)
    [BZOJ1876][SDOI2009]superGCD(高精度)
    [BZOJ1801][AHOI2009]中国象棋(递推)
    [bzoj2245][SDOI2011]工作安排(费用流)
    [bzoj 1064][NOI2008]假面舞会(dfs判断环)
    [BZOJ 1486][HNOI2009]最小圈(二分答案+dfs写的spfa判负环)
    2.3、操纵json、parquet、jdbc数据库
    输入框中的添加回车事件
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15909123.html
Copyright © 2020-2023  润新知