思路:
方案数是选一颗树到选n棵树(n+1)*n/2,每个方案是所有选法的长度和
看到一个大佬的思路,原来每一段的长度和还能这么算:
k∗sum(1+…n)−前缀和的前缀−后缀和的后缀 原文链接
(如选一颗,长度和就是都选一遍;选两颗,长度和就是除了第1棵和最后1棵选一遍,其余都选两遍)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;
ll a[N],num;
ll sum[N],sumk[N],sumx[N],sumy[N];
ll ksm(ll a,ll b){
ll ans=1;
a%=mod;
while(b){
if(b&1)
ans=(ll)ans*a%mod;
a=(ll)a*a%mod;
b>>=1;
}
return ans;
}
int main()
{
ll t, n, ans;
scanf("%lld", &t);
while (t--)
{
memset(sum, 0, sizeof sum);
memset(sumx, 0, sizeof sumx);
memset(sumy, 0, sizeof sumy);
memset(sumk, 0, sizeof sumk);
scanf("%lld", &n);
ans = 0;
for (ll i = 1ll; i <= n; i++)
scanf("%lld", &a[i]), sum[i] = (sum[i - 1ll] + a[i]) % mod;
for (ll i = 1ll; i <= n; i++)
sumx[i] = (sumx[i - 1ll] + sum[i]) % mod;
ll k = n;
for (ll i = 1ll; i <= n; i++)
sumy[i] = (sumy[i - 1ll] + a[k]) % mod, k--;
for (ll i = 1ll; i <= n; i++)
sumk[i] = (sumk[i - 1ll] + sumy[i]) % mod;
for (ll i = 1ll; i <= n; i++)
{
ans = (ans + ((((i * sum[n] % mod) - sumx[i - 1ll] - sumk[i - 1ll] + mod) % mod) * ksm(i, mod - 2ll) % mod)) % mod;
}
ll np = (((n + 1ll) * n) / 2ll) % mod;
printf("%lld\n", ((ans % mod) * (ksm(np, mod - 2ll) % mod) % mod));
}
}