// -*- coding:utf-8-unix -*- // #![feature(map_first_last)] #![allow(dead_code)] #![allow(unused_imports)] #![allow(unused_macros)] // use core::num; use std::cmp::*; use std::fmt::*; use std::hash::*; use std::io::BufRead; use std::iter::FromIterator; use std::*; use std::{cmp, collections, fmt, io, iter, ops, str}; const INF: i64 = 1223372036854775807; const UINF: usize = INF as usize; const LINF: i64 = 2147483647; const INF128: i128 = 1223372036854775807000000000000; const MOD1: i64 = 1000000007; const MOD9: i64 = 998244353; const MOD: i64 = MOD9; // const MOD: i64 = MOD2; const UMOD: usize = MOD as usize; const M_PI: f64 = 3.14159265358979323846; // use proconio::input; // const MOD: i64 = INF; use cmp::Ordering::*; use std::collections::*; use std::io::stdin; use std::io::stdout; use std::io::Write; macro_rules! p { ($x:expr) => { //if expr println!("{}", $x); }; } macro_rules! vp { // vector print separate with space ($x:expr) => { println!( "{}", $x.iter() .map(|x| x.to_string()) .collect::>() .join(" ") ); }; } macro_rules! d { ($x:expr) => { eprintln!("{:?}", $x); }; } macro_rules! yn { ($val:expr) => { if $val { println!("Yes"); } else { println!("No"); } }; } macro_rules! map{ // declear btreemap ($($key:expr => $val:expr),*) => { { let mut map = ::std::collections::BTreeMap::new(); $( map.insert($key, $val); )* map } }; } macro_rules! set{ // declear btreemap ($($key:expr),*) => { { let mut set = ::std::collections::BTreeSet::new(); $( set.insert($key); )* set } }; } //input output #[allow(dead_code)] fn read() -> T { let mut s = String::new(); std::io::stdin().read_line(&mut s).ok(); s.trim().parse().ok().unwrap() } #[allow(dead_code)] fn read_vec() -> Vec { read::() .split_whitespace() .map(|e| e.parse().ok().unwrap()) .collect() } #[allow(dead_code)] fn read_mat(n: u32) -> Vec> { (0..n).map(|_| read_vec()).collect() } #[allow(dead_code)] fn readii() -> (i64, i64) { let mut vec: Vec = read_vec(); (vec[0], vec[1]) } #[allow(dead_code)] fn readiii() -> (i64, i64, i64) { let mut vec: Vec = read_vec(); (vec[0], vec[1], vec[2]) } #[allow(dead_code)] fn readuu() -> (usize, usize) { let mut vec: Vec = read_vec(); (vec[0], vec[1]) } #[allow(dead_code)] fn readff() -> (f64, f64) { let mut vec: Vec = read_vec(); (vec[0], vec[1]) } fn readcc() -> (char, char) { let mut vec: Vec = read_vec(); (vec[0], vec[1]) } fn readuuu() -> (usize, usize, usize) { let mut vec: Vec = read_vec(); (vec[0], vec[1], vec[2]) } #[allow(dead_code)] fn readiiii() -> (i64, i64, i64, i64) { let mut vec: Vec = read_vec(); (vec[0], vec[1], vec[2], vec[3]) } #[allow(dead_code)] fn readuuuu() -> (usize, usize, usize, usize) { let mut vec: Vec = read_vec(); (vec[0], vec[1], vec[2], vec[3]) } use std::collections::VecDeque; macro_rules! M { (a :expr ) => { M::new({ a }) }; } #[derive(Copy, Clone, Debug)] pub struct M(i64); impl M { fn new(x: i64) -> Self { M(x.rem_euclid(MOD)) } fn pow(self, n: usize) -> Self { match n { 0 => M::new(1), _ => { let mut a = self.pow(n >> 1); a *= a; if n & 1 == 1 { a *= self; } a } } } fn inv(self) -> Self { self.pow((MOD - 2) as usize) } } impl std::ops::Neg for M { type Output = M; fn neg(self) -> Self::Output { Self::new(-self.0) } } impl std::ops::AddAssign for M { fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0; self.0 %= MOD; } } impl std::ops::AddAssign for M { fn add_assign(&mut self, rhs: i64) { *self += M::new(rhs); } } impl std::ops::AddAssign for M { fn add_assign(&mut self, rhs: usize) { *self += M::new(rhs as i64); } } impl std::ops::Add for M where M: std::ops::AddAssign, { type Output = Self; fn add(self, other: T) -> Self { let mut res = self; res += other; res } } impl std::ops::SubAssign for M { fn sub_assign(&mut self, rhs: Self) { self.0 -= rhs.0; if self.0 < 0 { self.0 %= MOD; self.0 += MOD; } } } impl std::ops::SubAssign for M { fn sub_assign(&mut self, rhs: i64) { *self -= M::new(rhs); if (*self).0 < 0 { self.0 %= MOD; self.0 += MOD; } } } impl std::ops::SubAssign for M { fn sub_assign(&mut self, rhs: usize) { *self -= M::new(rhs as i64); if (*self).0 < 0 { self.0 %= MOD; self.0 += MOD; } } } impl std::ops::Sub for M where M: std::ops::SubAssign, { type Output = Self; fn sub(self, other: T) -> Self { let mut res = self; res -= other; res } } impl std::ops::MulAssign for M { fn mul_assign(&mut self, rhs: Self) { self.0 %= MOD; self.0 *= (rhs.0 % MOD); self.0 %= MOD; } } impl std::ops::MulAssign for M { fn mul_assign(&mut self, rhs: i64) { *self *= M::new(rhs); } } impl std::ops::MulAssign for M { fn mul_assign(&mut self, rhs: usize) { *self *= M::new(rhs as i64); } } impl std::ops::Mul for M where M: std::ops::MulAssign, { type Output = Self; fn mul(self, other: T) -> Self { let mut res = self; res *= other; res } } impl std::ops::DivAssign for M { fn div_assign(&mut self, rhs: Self) { *self *= rhs.inv(); } } impl std::ops::DivAssign for M { fn div_assign(&mut self, rhs: i64) { *self /= M::new(rhs); } } impl std::ops::DivAssign for M { fn div_assign(&mut self, rhs: usize) { *self /= M::new(rhs as i64); } } impl std::ops::Div for M where M: std::ops::DivAssign, { type Output = Self; fn div(self, other: T) -> Self { let mut res = self; res /= other; res } } impl std::fmt::Display for M { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl std::ops::Deref for M { type Target = i64; fn deref(&self) -> &Self::Target { &self.0 } } impl std::ops::DerefMut for M { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } #[allow(dead_code)] pub fn gcd(a: usize, b: usize) -> usize { if b == 0 { a } else { gcd(b, a % b) } } #[allow(dead_code)] pub fn lcm(a: usize, b: usize) -> usize { a / gcd(a, b) * b } #[allow(dead_code)] /// (gcd, x, y) pub fn extgcd(a: i64, b: i64) -> (i64, i64, i64) { if b == 0 { (a, 1, 0) } else { let (gcd, x, y) = extgcd(b, a % b); (gcd, y, x - (a / b) * y) } } #[allow(dead_code)] /// x ^ n % m pub fn mod_pow(x: usize, n: usize, m: usize) -> usize { let mut res = 1; let mut x = x % m; let mut n = n; while n > 0 { if n & 1 == 1 { res = (res * x) % m; } x = (x * x) % m; n >>= 1; } res } pub struct Combination { m: usize, f_table: Vec, moi: Vec, } impl Combination { // 0 <= size <= 10^8 is constrained. pub fn new(mod_num: usize, table_size: usize) -> Self { Self { m: mod_num, f_table: vec![0; table_size], moi: vec![0; 0], } } pub fn build(&mut self) { let size = self.f_table.len(); self.f_table = self.fact_table(size, self.m); self.moi = self.fact_inv_table(size, self.m); } fn fact_table(&mut self, len: usize, m: usize) -> Vec { let mut res = vec![1; len + 1]; for i in 2..len + 1 { res[i] = (res[i - 1] * i) % m; } res } fn fact_inv_table(&mut self, len: usize, m: usize) -> Vec { let mut res = vec![1; len + 1]; let mut inv = vec![1; len + 1]; //inv[i] = MOD - inv[MOD%i] * (MOD / i) % MOD for i in 2..len { inv[i] = (m - inv[m % i] * (m / i) % m) % m; res[i] = inv[i] * res[i - 1]; // res[i] = self.mod_inverse(i, m) * res[i - 1]; // res[i] = 1; res[i] %= m; } res } pub fn p(&mut self, n: usize, k: usize) -> i64 { let p = MOD as usize; if k == 0 { return 1; } if n < k { 0 } else { let (a1, e1) = self.mod_fact(n, p); let (a2, e2) = self.mod_fact(k, p); let (a3, e3) = self.mod_fact(n - k, p); if e1 > e2 + e3 { 0 } else { let moi = self.mod_inverse(a3 % p, p); (a1 * self.mod_inverse(a3 % p, p) % p) as i64 } } } pub fn c(&mut self, n: usize, k: usize) -> i64 { let p = MOD as usize; if n == 0 && k == 0 { return 1; } if n == 0 { return 0; } if k == 0 { return 1; } if n < k { 0 } else { let (a1, e1) = self.mod_fact(n, p); let (a2, e2) = self.mod_fact(k, p); let (a3, e3) = self.mod_fact(n - k, p); if e1 > e2 + e3 { 0 } else { (((a1 * &self.moi[k]) % p * &self.moi[n - k]) % p) as i64 } } } pub fn h(&mut self, n: usize, k: usize) -> i64 { return self.c(n + k - 1, k); } pub fn factorial(&mut self, n: usize) -> i64 { return self.p(n, n); } fn extgcd(&mut self, a: i64, b: i64) -> (i64, i64, i64) { if b == 0 { (a, 1, 0) } else { let (gcd, x, y) = extgcd(b, a % b); (gcd, y, x - (a / b) * y) } } fn mod_inverse(&mut self, a: usize, m: usize) -> usize { let (_, x, _) = self.extgcd(a as i64, m as i64); ((m as i64 + x) as usize % m) % m } fn mod_fact(&mut self, n: usize, p: usize) -> (usize, usize) { if n == 0 { (1, 0) } else { let (a, b) = self.mod_fact(n / p, p); let pow = b + n / p; if n / p % 2 != 0 { (a * (p - self.f_table[(n % p) as usize]) % p, pow) } else { (a * self.f_table[(n % p) as usize] % p, pow) } } } } fn dfs(v: usize, p: usize, graph: &Vec>, dp: &mut Vec>, a: &Vec) { let mut mul = M(1); let mut sum = M(0); let mut sum_pow2 = M(0); let mut have_child = false; for &(u, w) in &graph[v] { if u == p { continue; } dfs(u, v, graph, dp, a); mul *= dp[u][0]; sum += dp[u][0]; sum_pow2 += dp[u][0] * dp[u][0]; have_child = true; } if !have_child { mul = M(0); } dp[v][0] = M(a[v] as i64) * (M(1) + sum); dp[v][1] = M(a[v] as i64) * (sum + (sum * sum - sum_pow2) / M(2)); } fn main() { let n: usize = read(); let mut a: Vec = read_vec(); let mut graph = vec![vec![(0 as usize, 0 as usize); (0) as usize]; (n) as usize]; for i in 0..n - 1 { let (mut a, mut b) = readuu(); a -= 1; b -= 1; graph[a].push((b, 1)); graph[b].push((a, 1)); } let mut dp = vec![vec![M(0), M(0)]; n]; dfs(0, n, &graph, &mut dp, &a); let mut res = M(0); for i in 0..n { res += dp[i][1]; } // d!(dp); println!("{}", res); }