1、题面:
2、思路:
(参考文章)
考虑每个节点对结果做出的贡献,
如果n = 4;
0节点的贡献是6 = 3!
1节点的贡献是12 = 3!+ 3!/1
2节点的贡献是15 = 3!+ 3!/1 + 3!/2
3节点的贡献是17 = 3!+ 3!/1 + 3!/2 + 3!/3
所以可以递推得到每个节点的贡献
第0个节点的贡献是 f(0) =(n-1)!
从1~n-1节点,每个节点的贡献是
从前向后递推得到每个点的贡献
f(i) = f(i-1) + (n-1)!/i
结果ans = ∑(f(i)*x)/n!;(x表示每个节点的权值)
将所有除法的地方用逆元代替求出最终的结果。
3、代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL MOD = 998244353;
const int maxn = 1e5+10;
LL fac[maxn];
LL POW(LL a,LL b){
LL ans = 1LL;
while(b){
if(b&1LL){
ans = ans*a%MOD;
}
a = a*a%MOD;
b>>=1LL;
}
return ans;
}
LL inv(LL b){
return POW(b,MOD-2)%MOD;
}
void Init(){
fac[0] = fac[1] = 1LL;
for(LL i=2;i<maxn;i++){
fac[i] = fac[i-1]*i%MOD;
}
}
int main(void){
int T;
Init();
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
LL x;
scanf("%lld",&x);
LL ans = x*fac[n-1]%MOD;
LL tmp = fac[n-1];
for(int i=1;i<n;i++){
scanf("%lld",&x);
tmp = (tmp+fac[n-1]%MOD*inv(i)%MOD)%MOD;
ans = (ans+tmp*x%MOD)%MOD;
}
ans = ans*inv(fac[n])%MOD;
printf("%lld\n",ans);
}
return 0;
}