【2021集训队出题】愚蠢的在线法官

【2021集训队出题】愚蠢的在线法官

by AmanoKumiko

Description

给出一颗\(n\)个点的树,再给出每个点的权值\(v\)

然后给出一个长度为\(k\)的数组\(A\)

然后对于\(k*k\)的矩阵,\(i,j∈[1,k]\)\(V_{i,j}=v_{lca(A_i,A_j)}\),求它的行列式

Input

第一行两个整数\(n,k\)

第二行\(n\)个数,表示权值

第三行\(k\)个数表示\(A\)

接下来\(n-1\)行,读入一颗树

Output

一行一个数表示答案对\(998244353\)取模的结果

Sample Input

3 2
1 2 3
2 3
1 2
1 3

Sample Output

5

Data Constraint

\(1\le n,k\le 5*10^5,v_i∈[0,998244353),A_i∈[1,n]\)

Solution

一些高代:

1.行列式交换两行取反

2.行列式中某一行提出一个公因子\(x\),行列式乘上\(x\)

3.行列式中某一行中\(a_i\)都表示成\(b_i+c_i\)的形式,那么行列式等于取\(b_i\)\(c_i\)情况下的和

4.行列式中两行相减,行列式不变

首先,如果\(A\)中存在相等的数,答案是\(0\)

然后我们考虑树形\(dp\)

\(f_i\)表示以\(i\)为根的子树的行列式

考虑加入一个子树时的贡献

那么变成这种形式

\[\left| \begin{array}{} A & B\\ C & D \end{array} \right| \]

\(A\)是原答案,\(D\)是子树的答案

\(x=v_u\),那么\(B,C\)均为\(x\)

我们直接给一行减去\(x\)

然后变成了

\[x\left| \begin{array}{} 1&1&1&1\\ a'&a'&0&0\\ 0&0&a'&a'\\ 0&0&a'&a' \end{array} \right| \]

\[\left| \begin{array}{} a&a&x&x\\ a&a&x&x\\ x&x&a&a\\ 0&0&a'&a' \end{array} \right| \]

的形式

对于前者,我们引入一个\(g_i\)表示在\(i\)的行列式中,将某一行全部变成\(1\)的答案

对于后者,我们可以继续让别的行减去\(x\),最后变为

\[\left| \begin{array}{} a'&a'&0&0\\ a'&a'&0&0\\ 0&0&a'&a'\\ 0&0&a'&a' \end{array} \right| \]

再令\(s=\prod_{v∈son(u)}f_v\)

那么有\(f_u=\sum_{v∈son(u)}\frac{g_vxs}{f_v}+s\)

而在这种情况下,

后代求的行列式实际上是后代所有\(v\)减去当前\(v\)的行列式,这个随便处理一下就可以了

对于\(g\)的递推,类似

然后再特判一下当前点在\(A\)中的情况就行了

Code

#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define Fs(i,a) for(int i=last[a];i;i=e[i].next)
#define LL long long
#define mo 998244353
#define N 500010

int n,k,a,b,A[N],vis[N],tot,last[N];
LL v[N],f[N],g[N],tag;

struct node{int en,next;}e[N*2];

void add(int x,int y){e[++tot]=(node){y,last[x]};last[x]=tot;}

LL mi(LL x,LL y){
	if(y==1)return x;
	return y%2?x*mi(x*x%mo,y/2)%mo:mi(x*x%mo,y/2);
}

void dfs(int now,int pre){
	v[now]=(v[now]-tag+mo)%mo;
	(tag+=v[now])%=mo;
	LL fs=1;int s=0;
	Fs(i,now)if(e[i].en!=pre)dfs(e[i].en,now),fs=fs*f[e[i].en]%mo,s++;
	if(vis[now]){
		if(!s)f[now]=v[now],g[now]=1;
		else f[now]=fs*v[now]%mo,g[now]=fs;
	}else{
		f[now]=fs;
		Fs(i,now)if(e[i].en!=pre){
			LL x=mi(f[e[i].en],mo-2);
			(f[now]+=fs*x%mo*g[e[i].en]%mo*v[now]%mo)%=mo;
			(g[now]+=fs*x%mo*g[e[i].en]%mo)%=mo;
		}
	}
	tag=(tag-v[now]+mo)%mo;
}

int main(){
	scanf("%d%d",&n,&k);
	F(i,1,n)scanf("%lld",&v[i]);
	F(i,1,k){
		scanf("%d",&A[i]);
		if(vis[A[i]]){printf("0");return 0;}
		vis[A[i]]=1;
	}
	F(i,1,n-1)scanf("%d%d",&a,&b),add(a,b),add(b,a);
	dfs(1,0);
	printf("%lld",f[1]);
	return 0;
}
posted @ 2021-12-22 22:23  冰雾  阅读(185)  评论(0编辑  收藏  举报