传送门哎
∑ i = 1 n − 1 ∑ j = i + 1 n f ( i , j ) \sum\limits_{i=1}^{n-1}\sum\limits_{j=i+1}^{n}f(i,j) i=1∑n−1j=i+1∑nf(i,j)
主 要 是 这 个 东 西 很 微 妙 主要是这个东西很微妙 主要是这个东西很微妙
怎 么 直 接 来 计 算 每 条 边 被 走 了 几 次 ? 怎么直接来计算每条边被走了几次? 怎么直接来计算每条边被走了几次?
现 在 有 一 条 u − v 的 边 , 去 掉 这 条 边 , 分 成 包 含 u 和 包 含 v 的 两 个 集 合 现在有一条u-v的边,去掉这条边,分成包含u和包含v的两个集合 现在有一条u−v的边,去掉这条边,分成包含u和包含v的两个集合
一 个 集 合 的 一 个 点 q 到 另 一 个 集 合 的 w 都 会 经 过 这 条 边 一个集合的一个点q到另一个集合的w都会经过这条边 一个集合的一个点q到另一个集合的w都会经过这条边
如 果 q > w 也 没 关 系 , 那 就 是 w − > q 的 路 上 经 过 这 条 边 如果q>w也没关系,那就是w->q的路上经过这条边 如果q>w也没关系,那就是w−>q的路上经过这条边
所 以 这 条 边 被 经 过 了 s i z e [ v ] ∗ ( n − s i z e [ v ] ) 次 所以这条边被经过了size[v]*(n-size[v])次 所以这条边被经过了size[v]∗(n−size[v])次
根 据 这 个 一 遍 d f s 现 在 得 出 了 数 组 a 保 存 每 条 边 经 过 几 次 根据这个一遍dfs现在得出了数组a保存每条边经过几次 根据这个一遍dfs现在得出了数组a保存每条边经过几次
假设m<=n-1
由 于 让 1 最 少 , 所 以 这 m 个 质 因 子 肯 定 全 选 由于让1最少,所以这m个质因子肯定全选 由于让1最少,所以这m个质因子肯定全选
贪 心 的 原 则 , 经 过 边 大 的 肯 定 分 配 权 值 大 的 , 分 配 完 了 只 能 分 配 1 了 贪心的原则,经过边大的肯定分配权值大的,分配完了只能分配1了 贪心的原则,经过边大的肯定分配权值大的,分配完了只能分配1了
假设m>=n-1
让1最少就是不选1
那 么 贪 心 的 让 [ n − 1 , m ] 的 质 因 子 合 并 成 一 个 超 级 大 的 质 因 子 那么贪心的让[n-1,m]的质因子合并成一个超级大的质因子 那么贪心的让[n−1,m]的质因子合并成一个超级大的质因子
然 后 一 一 匹 配 然后一一匹配 然后一一匹配
注意事项
s i z [ ] 数 组 不 要 取 模 , 后 续 要 排 序 贪 心 的 siz[]数组不要取模,后续要排序贪心的 siz[]数组不要取模,后续要排序贪心的
边 只 有 n − 1 条 , 注 意 和 p 数 组 配 对 的 情 况 边只有n-1条,注意和p数组配对的情况 边只有n−1条,注意和p数组配对的情况
#include
using namespace std;
#define int long long
const int maxn=5e5+10;
const int mod=1e9+7;
int t,n,p[maxn],a[maxn],siz[maxn],m;
struct edge{
int to,nxt;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v){
d[++cnt]=(edge){v,head[u]},head[u]=cnt;
}
void dfs(int u,int fa)
{
siz[u]=1;
for(int i=head[u];i;i=d[i].nxt)
{
int v=d[i].to;
if( v==fa ) continue;
dfs(v,u);
siz[u]+=siz[v];
a[i/2]=siz[v]*(n-siz[v]);
}
}
signed main()
{
cin >> t;
while( t-- )
{
cnt=1;
cin >> n;
for(int i=1;i> m;
for(int i=1;i<=m;i++) cin >> p[i];
sort(p+1,p+1+m);
sort(a+1,a+n);
int ans=0;
if( m<=n-1 )
{
for(int i=n-1,j=m;j>=1;i--,j--)
ans = (ans+a[i]*p[j]%mod )%mod;
for(int i=n-m-1;i>=1;i--)
ans=(ans+a[i])%mod;
cout << ans << endl;
}
else
{
for(int i=m-1;i>=n-1;i--)
p[i]=p[i]*p[i+1]%mod;
for(int i=n-1;i>=1;i--)
ans=(ans+a[i]*p[i]%mod )%mod;
cout << ans << '\n';
}
for(int i=0;i<=n*2;i++) head[i]=0,siz[i]=0;
for(int i=1;i<=m;i++) p[i]=0;
}
}