注意到一棵树
T
T
T 的价值只与每个点的度数有关,如果我们已经确定了每个点的度数
d
i
d_i
di,由 prufer序列 可知,对答案产生的贡献为(任意两个连通块
i
,
j
i,j
i,j 之间的连边方案有
a
i
a
j
a_ia_j
aiaj 种):
(
n
−
2
)
!
∏
i
=
1
n
(
d
i
−
1
)
!
(
∏
i
=
1
n
d
i
m
)
(
∑
i
=
1
n
d
i
m
)
(
∏
i
=
1
n
a
i
d
i
)
(
n
−
2
)
!
(
∑
i
=
1
n
d
i
m
)
(
∏
i
=
1
n
d
i
m
a
i
d
i
(
d
i
−
1
)
!
)
\begin{aligned} \frac{(n - 2)!}{\prod \limits_{i = 1}^{n}(d_i - 1)!}\left(\prod \limits_{i = 1}^{n}d_i ^m\right)\left( \sum \limits_{i = 1}^{n}d_i^m\right) \left(\prod \limits_{i = 1}^{n}a_i^{d_i}\right)\\ (n - 2)! \left(\sum \limits_{i = 1}^{n}d_i^m\right)\left(\prod \limits_{i = 1}^{n}\frac{d_i^ma_i^{d_i}}{(d_i - 1)!}\right) \end{aligned}
i=1∏n(di−1)!(n−2)!(i=1∏ndim)(i=1∑ndim)(i=1∏naidi)(n−2)!(i=1∑ndim)(i=1∏n(di−1)!dimaidi)
前面的和式很不好处理,考虑和式的实际意义。
首先枚举某一个点
i
i
i 的度数
d
i
d_i
di,乘积的部分可以看做给剩余的点分配度数,可以用一个背包
DP
\text{DP}
DP 解决,然后将这一部分的贡献乘上
d
i
m
d_i^m
dim 加到答案中。
预处理出前后缀的
DP
\text{DP}
DP 数组,在枚举到每个点的时候暴力合并即可,时间复杂度
O
(
n
3
)
\mathcal O(n^3)
O(n3),期望得分
20pts
\text{20pts}
20pts。
Algorithm 2
不难发现,转移是卷积的形式,NTT 优化即可。
具体地,设生成函数
F
(
x
)
=
∑
i
=
0
n
−
2
(
i
+
1
)
m
i
!
x
i
G
(
x
)
=
∑
i
=
0
n
−
2
(
i
+
1
)
2
m
i
!
x
i
\begin{aligned} F(x) = \sum \limits_{i = 0}^{n - 2}\frac{(i + 1)^m}{i!}x^i \\ G(x) = \sum \limits_{i = 0}^{n - 2}\frac{(i + 1)^{2m}}{i!}x^i \end{aligned}
F(x)=i=0∑n−2i!(i+1)mxiG(x)=i=0∑n−2i!(i+1)2mxi
则答案可以表示为:
(
(
n
−
2
)
!
∏
i
=
1
n
a
i
)
[
x
n
−
2
]
(
∑
i
=
1
n
G
(
a
i
x
)
∏
j
≠
i
j
=
1
j
=
n
F
(
a
j
x
)
)
\begin{aligned} \left((n - 2)! \prod \limits_{i = 1}^{n} a_i \right) [x^{n - 2}]\left(\sum \limits_{i = 1}^{n}G(a_ix) \prod \limits_{^{j = 1}_{j \neq i}}^{j = n} F(a_jx)\right)\\ \end{aligned}
((n−2)!i=1∏nai)[xn−2]⎝⎜⎛i=1∑nG(aix)j=ij=1∏j=nF(ajx)⎠⎟⎞
时间复杂度
O
(
n
2
log
n
)
\mathcal O(n^2 \log n)
O(n2logn),期望得分
40pts
\text{40pts}
40pts。
常数较大,需要尽量减小 NTT 的次数。
Algorithm 3
针对所有
a
i
a_i
ai 相同的数据。
显然此时每个点产生的贡献相同,答案可以简化为:
(
n
(
n
−
2
)
!
∏
i
=
1
n
a
i
)
[
x
n
−
2
]
(
G
(
a
1
x
)
F
(
a
1
x
)
n
−
1
)
\begin{aligned} \left(n(n - 2)! \prod \limits_{i = 1}^{n} a_i \right) [x^{n - 2}]\left(G(a_1x) F(a_1x)^{n - 1}\right)\\ \end{aligned}
(n(n−2)!i=1∏nai)[xn−2](G(a1x)F(a1x)n−1)
多项式快速幂即可,时间复杂度
O
(
n
log
2
n
)
\mathcal O(n \log^2 n)
O(nlog2n),结合
Algorithm 2
\text{Algorithm 2}
Algorithm 2 期望得分
60pts
\text{60pts}
60pts。
Code 1
60pts
\text{60pts}
60pts
#include<bits/stdc++.h>template<classT>inlinevoidread(T &res){char ch;while(ch =getchar(),!isdigit(ch));
res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+ ch -48;}constint N =3e4+5;constint M =12e4+5;constint mod =998244353;constint inv3 =(mod +1)/3;int n, m, ans;int a[N], ex_m[N], fra[N], inv[N];int rev[M], tw[M];inlineintquick_pow(int x,int k){int res =1;while(k){if(k &1)
res =1ll* res * x % mod;
x =1ll* x * x % mod;
k >>=1;}return res;}inlinevoidadd(int&x,int y){
x += y;
x >= mod ? x -= mod :0;}inlinevoiddec(int&x,int y){
x -= y;
x <0? x += mod :0;}inlinevoidNTT(int*f,int fm,int opt){int g = opt ==1?3: inv3;for(int i =0; i < fm;++i)if(i < rev[i])
std::swap(f[i], f[rev[i]]);for(int k =1; k < fm; k <<=1){int w =quick_pow(g,(mod -1)/(k <<1));
tw[0]=1;for(int j =1; j < k;++j)
tw[j]=1ll* tw[j -1]* w % mod;for(int i =0; i < fm; i += k <<1)for(int j =0,*f1 = f + i,*f2 = f + i + k; j < k;++j,++f1,++f2){int u =*f1,
v =1ll* tw[j]*(*f2)% mod;*f1 =*f2 = u;add(*f1, v);dec(*f2, v);}}if(opt ==-1){for(int i =0, inv =quick_pow(fm, mod -2); i < fm;++i)
f[i]=1ll* f[i]* inv % mod;}}constint N1 =3e3+5;constint M1 =12e3+5;int val[N1][N1], pre[N1][N1], suf[N1][N1];int val_val[N1][M1], pre_val[N1][M1], suf_val[N1][M1];int f[M], g[M], h[M], tmp_g[M];inlinevoidpoly_mul(int*a,int*b,int am,int fm){NTT(a, fm,1);NTT(b, fm,1);for(int i =0; i < fm;++i)
a[i]=1ll* a[i]* b[i]% mod;NTT(a, fm,-1);for(int i = am +1; i < fm;++i)
a[i]=0;for(int i =0; i < fm;++i)
b[i]=0;}inlinevoidpoly_self(int*a,int am,int fm){NTT(a, fm,1);for(int i =0; i < fm;++i)
a[i]=1ll* a[i]* a[i]% mod;NTT(a, fm,-1);for(int i = am +1; i < fm;++i)
a[i]=0;}inlinevoidwrite(int*a,int*b,int am,int fm){for(int i =0; i < fm;++i)
f[i]=0;for(int i =0; i <= am;++i)
f[i]= a[i];NTT(f, fm,1);for(int i =0; i < fm;++i)
b[i]= f[i];for(int i =0; i < fm;++i)
f[i]=0;}namespace task1
{inlinevoidwork(){
pre[0][0]= suf[n +1][0]=1;for(int i =1; i <= n;++i){int res =1;for(int j =1; j < n;++j){
res =1ll* res * a[i]% mod;
val[i][j]=1ll* ex_m[j]* inv[j -1]% mod * res % mod;}}int tmp = n -1<<1;for(int i =1; i <= n;++i)for(int j =1; j < n;++j)for(int k = j; k <= tmp;++k)
pre[i][k]=(1ll* pre[i -1][k - j]* val[i][j]+ pre[i][k])% mod;for(int i = n; i >=1;--i)for(int j =1; j < n;++j)for(int k = j; k <= tmp;++k)
suf[i][k]=(1ll* suf[i +1][k - j]* val[i][j]+ suf[i][k])% mod;for(int i =1; i <= n;++i){for(int k =0; k <= tmp;++k)
g[k]=0;for(int j =0; j <= tmp;++j)for(int k =0; j + k <= tmp;++k)
g[j + k]=(1ll* pre[i -1][j]* suf[i +1][k]+ g[j + k])% mod;for(int j =1; j < n;++j)
ans =(1ll* ex_m[j]* val[i][j]% mod * g[tmp - j]+ ans)% mod;}printf("%d\n",1ll* fra[n -2]* ans % mod);}}namespace task2
{inlinevoidwork(){int tot = n -2<<1, tmp = n -2, fm, k =-1;for(fm =1; fm <= tot; fm <<=1,++k);for(int i =1; i < fm;++i)
rev[i]=(rev[i >>1]>>1)|((i &1)<< k);
pre[0][0]= suf[n +1][0]=1;write(pre[0], pre_val[0], tmp, fm);write(suf[n +1], suf_val[n +1], tmp, fm);for(int i =1; i <= n;++i){int res =1;for(int j =1; j < n;++j){
res =1ll* res * a[i]% mod;
val[i][j -1]=1ll* ex_m[j]* inv[j -1]% mod * res % mod;}write(val[i], val_val[i], tmp, fm);}for(int i =1; i <= n;++i){for(int j =0; j < fm;++j)
f[j]=1ll* pre_val[i -1][j]* val_val[i][j]% mod;NTT(f, fm,-1);for(int j =0; j <= tmp;++j)
pre[i][j]= f[j];write(pre[i], pre_val[i], tmp, fm);}for(int i = n; i >=1;--i){for(int j =0; j < fm;++j)
f[j]=1ll* suf_val[i +1][j]* val_val[i][j]% mod;NTT(f, fm,-1);for(int j =0; j <= tmp;++j)
suf[i][j]= f[j];write(suf[i], suf_val[i], tmp, fm);}for(int i =1; i <= n;++i){for(int j =0; j < fm;++j)
f[j]=1ll* pre_val[i -1][j]* suf_val[i +1][j]% mod;NTT(f, fm,-1);for(int j =1; j < n;++j)
ans =(1ll* ex_m[j]* val[i][j -1]% mod * f[tmp - j +1]+ ans)% mod;}printf("%d\n",1ll* fra[n -2]* ans % mod);}}namespace task3
{inlinevoidwork(){int tot = n -2<<1, tmp = n -2, fm, k =-1;for(fm =1; fm <= tot; fm <<=1,++k);for(int i =1; i < fm;++i)
rev[i]=(rev[i >>1]>>1)|((i &1)<< k);int res =1;for(int i =0; i <= tmp;++i){
res =1ll* res * a[1]% mod;
g[i]=1ll* ex_m[i +1]* inv[i]% mod * res % mod;
f[i]=1ll* g[i]* ex_m[i +1]% mod;}
h[0]=1;
k = n -1;while(k){if(k &1){for(int i =0; i <= tmp;++i)
tmp_g[i]= g[i];poly_mul(h, tmp_g, tmp, fm);}poly_self(g, tmp, fm);
k >>=1;}poly_mul(f, h, tmp, fm);printf("%d\n",1ll* n * fra[n -2]% mod * f[n -2]% mod);}}intmain(){read(n);read(m);if(n ==1)returnputs(m ==0?"1":"0"),0;for(int i =1; i <= n;++i)read(a[i]);for(int i =1; i <= n;++i)
ex_m[i]=quick_pow(i, m);
fra[0]=1;for(int i =1; i <= n;++i)
fra[i]=1ll* fra[i -1]* i % mod;
inv[n]=quick_pow(fra[n], mod -2);for(int i = n; i >=1;--i)
inv[i -1]=1ll* inv[i]* i % mod;if(n <=500)
task1::work();elseif(n <=3000)
task2::work();else
task3::work();}
Algorithm 4
针对
m
=
1
m = 1
m=1 的数据。
此时
∑
i
=
1
n
d
i
m
=
2
n
−
2
\sum \limits_{i = 1}^{n}d_i^m = 2n - 2
i=1∑ndim=2n−2,答案可以简化为:
(
(
n
−
2
)
!
(
2
n
−
2
)
∏
i
=
1
n
a
i
)
[
x
n
−
2
]
∏
i
=
1
n
F
(
a
i
x
)
\begin{aligned} \left((n - 2)!(2n - 2)\prod\limits_{i = 1}^{n}a_i\right) [x^{n - 2}] \prod \limits_{i = 1}^{n}F(a_ix) \end{aligned}
((n−2)!(2n−2)i=1∏nai)[xn−2]i=1∏nF(aix)
难点在于
∏
i
=
1
n
F
(
a
i
x
)
(
m
o
d
x
n
−
1
)
\prod \limits_{i = 1}^{n}F(a_ix) (\mod x^{n - 1})
i=1∏nF(aix)(modxn−1) 怎么计算。
注意到求和比乘积容易很多,可以先对所有
F
F
F 取
ln
\ln
ln 求和然后再
exp
\exp
exp 回来,这样就可以把
a
i
a_i
ai 提取出来,答案可以转化为:
(
(
n
−
2
)
!
(
2
n
−
2
)
∏
i
=
1
n
a
i
)
[
x
n
−
2
]
exp
(
∑
j
=
0
n
−
2
[
x
j
]
ln
F
(
x
)
∑
i
=
1
n
a
i
j
)
\begin{aligned} \left((n - 2)!(2n - 2) \prod \limits_{i = 1}^{n}a_i\right)[x^{n - 2}] \exp\left( \sum \limits_{j = 0}^{n - 2}[x^{j}]\ln F(x) \sum\limits_{i = 1}^{n}a_i^j\right) \end{aligned}
((n−2)!(2n−2)i=1∏nai)[xn−2]exp(j=0∑n−2[xj]lnF(x)i=1∑naij)
现在只需要对于每个
j
(
0
≤
j
≤
n
−
2
)
j(0 \le j \le n - 2)
j(0≤j≤n−2),求出
∑
i
=
1
n
a
i
j
\sum \limits_{i = 1}^{n}a_i^j
i=1∑naij。
考虑生成函数
H
i
(
x
)
=
∑
j
=
0
∞
a
i
j
x
j
=
1
1
−
a
i
x
\begin{aligned} H_i(x) = \sum \limits_{j = 0}^{\infty} {a_i^jx^j} = \frac{1}{1 - a_ix} \end{aligned}
Hi(x)=j=0∑∞aijxj=1−aix1
我们所要求的就是
H
(
x
)
=
∑
i
=
1
n
H
i
(
x
)
=
∑
i
=
1
n
1
1
−
a
i
x
(
m
o
d
x
n
−
1
)
\begin{aligned} H(x)=\sum \limits_{i = 1}^{n} H_i(x) = \sum \limits_{i=1}^{n}\frac{1}{1-a_ix} (\mod x^{n - 1})\\ \end{aligned}
H(x)=i=1∑nHi(x)=i=1∑n1−aix1(modxn−1)
可以用类似 分治FFT 的过程模拟分式的相加,求出分子和分母的多项式,对分母求逆后与分子相乘。
时间复杂度
O
(
n
log
n
)
\mathcal O(n \log n)
O(nlogn),结合
Algorithm 2
\text{Algorithm 2}
Algorithm 2 和
Algorithm 3
\text{Algorithm 3}
Algorithm 3 期望得分
70pts
\text{70pts}
70pts。
首先把不等于的限制去掉,答案可变为:
(
(
n
−
2
)
!
∏
i
=
1
n
a
i
)
[
x
n
−
2
]
(
(
∑
i
=
1
n
G
F
(
a
i
x
)
)
(
∏
i
=
1
n
F
(
a
i
x
)
)
)
\begin{aligned} \left((n - 2)! \prod \limits_{i = 1}^{n} a_i \right) [x^{n - 2}]\left(\left(\sum \limits_{i = 1}^{n}\frac{G}{F}(a_ix) \right) \left(\prod \limits_{i = 1}^{n} F(a_ix)\right)\right)\\ \end{aligned}
((n−2)!i=1∏nai)[xn−2]((i=1∑nFG(aix))(i=1∏nF(aix)))
类似
Algorithm 4
\text{Algorithm 4}
Algorithm 4 中处理自变量中含有
a
a
a 的情况:
(
(
n
−
2
)
!
∏
i
=
1
n
a
i
)
[
x
n
−
2
]
(
(
∑
i
=
0
n
−
2
(
[
x
i
]
G
F
(
x
)
)
(
∑
j
=
1
n
a
j
i
)
)
exp
(
∑
i
=
0
n
−
2
[
x
i
]
ln
F
(
x
)
(
∑
j
=
1
n
a
j
i
)
)
)
\begin{aligned} \left((n - 2)! \prod \limits_{i = 1}^{n} a_i \right) [x^{n - 2}] \left(\left(\sum \limits_{i = 0}^{n - 2} \left([x^i]\frac{G}{F}(x)\right) \left(\sum \limits_{j = 1}^{n}a_j^i \right)\right)\exp\left(\sum \limits_{i = 0}^{n-2} [x^i]\ln F(x) \left(\sum \limits_{j = 1}^{n}a_j^i \right)\right)\right) \\ \end{aligned}
((n−2)!i=1∏nai)[xn−2]((i=0∑n−2([xi]FG(x))(j=1∑naji))exp(i=0∑n−2[xi]lnF(x)(j=1∑naji)))
简化一下得到:
(
(
n
−
2
)
!
∏
i
=
1
n
a
i
)
[
x
n
−
2
]
(
(
∑
i
=
0
n
−
2
[
x
i
]
G
F
(
x
)
[
x
i
]
H
(
x
)
)
exp
(
∑
i
=
0
n
−
2
[
x
i
]
ln
F
(
x
)
[
x
i
]
H
(
x
)
)
)
\begin{aligned} \left((n - 2)! \prod \limits_{i = 1}^{n} a_i \right) [x^{n - 2}] \left(\left(\sum \limits_{i = 0}^{n - 2} [x^i]\frac{G}{F}(x) [x^i]H(x)\right)\exp\left(\sum \limits_{i = 0}^{n - 2} [x^i]\ln F(x) [x^i]H(x)\right)\right) \\ \end{aligned}
((n−2)!i=1∏nai)[xn−2]((i=0∑n−2[xi]FG(x)[xi]H(x))exp(i=0∑n−2[xi]lnF(x)[xi]H(x)))
直接计算即可,时间复杂度
O
(
n
log
2
n
+
n
ln
n
log
m
)
\mathcal O(n \log^2 n + \frac{n}{\ln n} \log m)
O(nlog2n+lnnnlogm),期望得分
100pts
\text{100pts}
100pts。
Code 2
100pts
\text{100pts}
100pts
#include<bits/stdc++.h>template<classT>inlinevoidread(T &res){char ch;while(ch =getchar(),!isdigit(ch));
res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+ ch -48;}using std::vector;constint N =3e4+5;constint N4 =12e4+5;constint N8 =24e4+5;constint mod =998244353;constint inv3 =(mod +1)/3;bool vis[N];int tw[N8], rev[N8], inv[N8];int a[N], ex_m[N], ex_2m[N], pri[N], fra[N], inv_fra[N];int pr, n, m;template<classT>inline T Max(T x, T y){return x > y ? x : y;}inlineintquick_pow(int x,int k){int res =1;while(k){if(k &1)
res =1ll* res * x % mod;
x =1ll* x * x % mod;
k >>=1;}return res;}inlinevoidadd(int&x,int y){
x += y;
x >= mod ? x -= mod :0;}inlinevoiddec(int&x,int y){
x -= y;
x <0? x += mod :0;}struct poly
{
vector<int> f;int fm;inlinevoidNTT(int opt){int g = opt ==1?3: inv3;for(int i =0; i < fm;++i)if(i < rev[i])
std::swap(f[i], f[rev[i]]);for(int k =1; k < fm; k <<=1){int w =quick_pow(g,(mod -1)/(k <<1));
tw[0]=1;for(int i =1; i < k;++i)
tw[i]=1ll* tw[i -1]* w % mod;for(int i =0; i < fm; i += k <<1)for(int j =0; j < k;++j){int&x = f[i + j],&y = f[i + j + k];int u = x,
v =1ll* tw[j]* y % mod;
x = y = u;add(x, v);dec(y, v);}}if(opt ==-1){for(int i =0, inv =quick_pow(fm, mod -2); i < fm;++i)
f[i]=1ll* f[i]* inv % mod;}}}tr1[N4], tr2[N4], sum;
poly inv_a, exp_a, ln_a, _a, b;
poly F, G, tmp;inline poly operator*(poly a, poly b){int tot = a.fm + b.fm, fm, k =-1;for(fm =1; fm <= tot; fm <<=1,++k);for(int i =1; i < fm;++i)
rev[i]=(rev[i >>1]>>1)|((i &1)<< k);
a.fm = fm;
a.f.resize(fm);
b.fm = fm;
b.f.resize(fm);
a.NTT(1);
b.NTT(1);for(int i =0; i < fm;++i)
a.f[i]=1ll* a.f[i]* b.f[i]% mod;
a.NTT(-1);
a.fm = tot;
a.f.resize(tot +1);return a;}inline poly operator*(poly a,constint&k){for(int i =0; i <= a.fm;++i)
a.f[i]=1ll* a.f[i]* k % mod;return a;}inline poly operator+(poly a, poly b){int fm =Max(a.fm, b.fm);
a.f.resize(fm +1);
b.f.resize(fm +1);for(int i =0; i <= fm;++i)add(a.f[i], b.f[i]);
a.fm = fm;return a;}inline poly operator/(poly a, poly b){for(int i =0; i <= a.fm;++i)
a.f[i]=1ll* a.f[i]* b.f[i]% mod;return a;}inline poly poly_inv(poly a){
inv_a.fm =0;
inv_a.f.resize(1);
inv_a.f[0]=quick_pow(a.f[0], mod -2);int k =1, cnt =0;while(k <= a.fm){
k <<=1,++cnt;int fm = k <<1;for(int i =1; i < fm;++i)
rev[i]=(rev[i >>1]>>1)|((i &1)<< cnt);
inv_a.fm = fm;
inv_a.f.resize(fm);
inv_a.NTT(1);
_a.fm = fm;
_a.f.resize(fm);for(int i =0; i < k;++i)
_a.f[i]= i <= a.fm ? a.f[i]:0;
_a.NTT(1);for(int i =0; i < fm;++i){int tmp = inv_a.f[i];add(inv_a.f[i], tmp);dec(inv_a.f[i],1ll* _a.f[i]* tmp % mod * tmp % mod);}
inv_a.NTT(-1);
inv_a.fm = k;
inv_a.f.resize(k);
_a.f.clear();}
inv_a.fm = a.fm;
inv_a.f.resize(a.fm +1);return inv_a;}inline poly poly_der(poly a){for(int i =0; i < a.fm;++i)
a.f[i]=1ll* a.f[i +1]*(i +1)% mod;--a.fm;
a.f.resize(a.fm +1);return a;}inline poly poly_int(poly a){++a.fm;
a.f.resize(a.fm +1);for(int i = a.fm; i >=1;--i)
a.f[i]=1ll* a.f[i -1]* inv[i]% mod;
a.f[0]=0;return a;}inline poly poly_ln(poly a){
b =poly_der(a)*poly_inv(a);
b.fm = a.fm -1;
b.f.resize(a.fm);returnpoly_int(b);}inline poly poly_exp(poly a){
exp_a.fm =0;
exp_a.f.resize(1);
exp_a.f[0]=1;int k =1, cnt =0;while(k <= a.fm){
ln_a.f.clear();
inv_a.f.clear();
b.f.clear();
k <<=1,++cnt;int fm = k <<1;
exp_a.fm = k -1;
exp_a.f.resize(k);
ln_a =poly_ln(exp_a);
ln_a.fm = fm;
ln_a.f.resize(fm);
exp_a.fm = fm;
exp_a.f.resize(fm);for(int i =0; i < k;++i){
ln_a.f[i]? ln_a.f[i]= mod - ln_a.f[i]:0;if(i <= a.fm)add(ln_a.f[i], a.f[i]);}add(ln_a.f[0],1);for(int i =1; i < fm;++i)
rev[i]=(rev[i >>1]>>1)|((i &1)<< cnt);
ln_a.NTT(1);
exp_a.NTT(1);for(int i =0; i < fm;++i)
exp_a.f[i]=1ll* exp_a.f[i]* ln_a.f[i]% mod;
exp_a.NTT(-1);
exp_a.fm = k -1;
exp_a.f.resize(k);
ln_a.f.clear();}
exp_a.fm = a.fm;
exp_a.f.resize(a.fm +1);return exp_a;}#define sL s << 1#define sR s << 1 | 1inlinevoidsolve(int s,int l,int r){if(l == r){
tr1[s].fm =0;
tr1[s].f.resize(1);
tr1[s].f[0]=1;
tr2[s].fm =1;
tr2[s].f.resize(2);
tr2[s].f[0]=1;dec(tr2[s].f[1], a[l]);return;}int mid = l + r >>1;solve(sL, l, mid);solve(sR, mid +1, r);
tr1[s]= tr1[sL]* tr2[sR]+ tr2[sL]* tr1[sR];
tr2[s]= tr2[sL]* tr2[sR];}intmain(){read(n);read(m);if(n ==1)returnputs(m ==0?"1":"0"),0;
fra[0]=1;for(int i =1; i < n;++i)
fra[i]=1ll* fra[i -1]* i % mod;
inv_fra[n -1]=quick_pow(fra[n -1], mod -2);for(int i = n -1; i >=1;--i)
inv_fra[i -1]=1ll* inv_fra[i]* i % mod;
inv[0]= inv[1]=1;for(int i =2, im = n <<2; i <= im;++i)
inv[i]=1ll*(mod - mod / i)* inv[mod % i]% mod;int prod = fra[n -2];for(int i =1; i <= n;++i){read(a[i]);
prod =1ll* prod * a[i]% mod;}
ex_m[1]=1;for(int i =1; i < n;++i){if(!vis[i]){
pri[++pr]= i;
ex_m[i]=quick_pow(i, m);}for(int j =1; j <= pr &&1ll* pri[j]* i < n;++j){int tmp = pri[j]* i;
vis[tmp]=true;
ex_m[tmp]=1ll* ex_m[i]* ex_m[pri[j]]% mod;if(i % pri[j]==0)break;}}for(int i =1; i < n;++i)
ex_2m[i]=1ll* ex_m[i]* ex_m[i]% mod;solve(1,1, n);
sum = tr1[1]*poly_inv(tr2[1]);
sum.fm = n -2;
sum.f.resize(n -1);
F.fm = n -2;
F.f.resize(n -1);
G.fm = n -2;
G.f.resize(n -1);for(int i =0; i <= n -2;++i)
F.f[i]=1ll* ex_m[i +1]* inv_fra[i]% mod;for(int i =0; i <= n -2;++i)
G.f[i]=1ll* ex_2m[i +1]* inv_fra[i]% mod;
tmp = G *poly_inv(F);
tmp.fm = n -2;
tmp.f.resize(n -1);printf("%d\n",1ll* prod *((tmp / sum)*poly_exp(poly_ln(F)/ sum)).f[n -2]% mod);}