题意:
解法:
n个点,
0号点有1种选法,
1号点有1种选法,
2号点有2种选法,
...
n-1号点有n-1种选法.
因此树的形态总共有(n-1)!种.
然后随机选择一颗子树,
因为有n个点,所以最后的选择有(n-1)!*n =n!种可能.
考虑每个点对答案的贡献,
考虑每个点在所有选择出的子树中,有多少种被包含.
0:(n-1)!种,
只有选择点0的时候才会被包含.
1:(n-1)!+(n-1)!种,
选择点0和点1的时包含1.
2:(n-1)!+(n-1)!/2+(n-1)!种,
选择点0,点1(2不在0下面),点2.
3:(n-1)!+(n-1)!/2+(n-1)!/3+(n-1)!种,
选择点0,点1(3不在0下面),点2(3不在01下面),点3.
可以推出:
k:(n-1)!/1+(n-1)!/2+(n-1)!/3....(n-1)!/k+(n-1)!种.
设点k的出现种数为cnt[k],权值为a[k],
那么点k对答案的贡献为cnt[k]*a[k]/(n!).
累加所有点的贡献就是答案.
code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e6+5;
const int mod=998244353;
int fac[maxm];
int a[maxm];
int n;
int ppow(int a,int b,int mod){
int ans=1%mod;a%=mod;
for(;b;b>>=1,a=a*a%mod)if(b&1)ans=ans*a%mod;
return ans;
}
void init(){
fac[0]=1;
for(int i=1;i<maxm;i++)fac[i]=fac[i-1]*i%mod;
}
void solve(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
int ans=0;
int cnt=fac[n-1];
ans=(ans+cnt*a[0]%mod)%mod;
for(int i=1;i<n;i++){
cnt=(cnt+fac[n-1]*ppow(i,mod-2,mod)%mod)%mod;
ans=(ans+cnt*a[i]%mod)%mod;
}
ans=ans*ppow(fac[n],mod-2,mod)%mod;
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
init();
int T;cin>>T;
while(T--){
solve();
}
return 0;
}