Codeforces Round #665 (Div. 2)D. Maximum Distributed Tree

Title

CodeForces 1401 D. Maximum Distributed Tree

Time Limit

2 seconds

Memory Limit

256 megabytes

Problem Description

You are given a tree that consists of n n n nodes. You should label each of its n − 1 n-1 n1 edges with an integer in such way that satisfies the following conditions:

Let’s define f ( u , v ) f(u,v) f(u,v) as the sum of the numbers on the simple path from node u u u to node v v v. Also, let ∑ 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=1n1j=i+1nf(i,j) be a distribution index of the tree.

Find the maximum possible distribution index you can get. Since answer can be too large, print it modulo 1 0 9 + 7 10^9 + 7 109+7.

In this problem, since the number k k k can be large, the result of the prime factorization of k k k is given instead.

Input

The first line contains one integer t t t ( 1 ≤ t ≤ 100 1 \le t \le 100 1t100) — the number of test cases.

The first line of each test case contains a single integer n n n ( 2 ≤ n ≤ 1 0 5 2 \le n \le 10^5 2n105) — the number of nodes in the tree.

Each of the next n − 1 n-1 n1 lines describes an edge: the i i i-th line contains two integers u i u_i ui and v i v_i vi ( 1 ≤ u i , v i ≤ n 1 \le u_i, v_i \le n 1ui,vin; u i ≠ v i u_i \ne v_i ui=vi) — indices of vertices connected by the i i i-th edge.

Next line contains a single integer m m m ( 1 ≤ m ≤ 6 ⋅ 1 0 4 1 \le m \le 6 \cdot 10^4 1m6104) — the number of prime factors of k k k.

Next line contains m m m prime numbers p 1 , p 2 , … , p m p_1, p_2, \ldots, p_m p1,p2,,pm ( 2 ≤ p i < 6 ⋅ 1 0 4 2 \le p_i < 6 \cdot 10^4 2pi<6104) such that k = p 1 ⋅ p 2 ⋅ … ⋅ p m k = p_1 \cdot p_2 \cdot \ldots \cdot p_m k=p1p2pm.

It is guaranteed that the sum of n n n over all test cases doesn’t exceed 1 0 5 10^5 105, the sum of m m m over all test cases doesn’t exceed 6 ⋅ 1 0 4 6 \cdot 10^4 6104, and the given edges for each test cases form a tree.

Output

Print the maximum distribution index you can get. Since answer can be too large, print it modulo 1 0 9 + 7 10^9+7 109+7.

Sample Input

3
4
1 2
2 3
3 4
2
2 2
4
3 4
1 3
3 2
2
3 2
7
6 1
2 3
4 6
7 3
5 1
3 6
4
7 5 13 3

Sample Onput

17
18
286

Note

In the first test case, one of the optimal ways is on the following image:

In this case, f ( 1 , 2 ) = 1 f(1,2)=1 f(1,2)=1, f ( 1 , 3 ) = 3 f(1,3)=3 f(1,3)=3, f ( 1 , 4 ) = 5 f(1,4)=5 f(1,4)=5, f ( 2 , 3 ) = 2 f(2,3)=2 f(2,3)=2, f ( 2 , 4 ) = 4 f(2,4)=4 f(2,4)=4, f ( 3 , 4 ) = 2 f(3,4)=2 f(3,4)=2, so the sum of these 6 6 6 numbers is 17 17 17.

In the second test case, one of the optimal ways is on the following image:

In this case, f ( 1 , 2 ) = 3 f(1,2)=3 f(1,2)=3, f ( 1 , 3 ) = 1 f(1,3)=1 f(1,3)=1, f ( 1 , 4 ) = 4 f(1,4)=4 f(1,4)=4, f ( 2 , 3 ) = 2 f(2,3)=2 f(2,3)=2, f ( 2 , 4 ) = 5 f(2,4)=5 f(2,4)=5, f ( 3 , 4 ) = 3 f(3,4)=3 f(3,4)=3, so the sum of these 6 6 6 numbers is 18 18 18.

Source

CodeForces 1401 D. Maximum Distributed Tree

题意

给一棵树 你可以任意分配边权

但要使得所有边权乘积 = = k ==k ==k

k是按质因子形式给出

f ( i , j ) f(i,j) f(i,j) i i i j j j路径边权和。

要使得所有点对边权和 ∑ 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=1n1j=i+1nf(i,j)最大。

思路

经典所有点对边权和,对每条边来说贡献就是左边点的个数*右边点的个数。

求出来排个序。

对于 k k k来说

如果他的质因子个数不足 n − 1 n-1 n1则补 1 1 1即可

如果超过 n − 1 n-1 n1呢?

则思考两两乘起来合并

是大的两两合并更优(粗略证明

设质因子为 p 0 p 1 p 2 p0 p1 p2 p0p1p2

边数贡献为 c 0 c 1 c0c1 c0c1

均从大到小排序

p 0 ∗ c 0 + p 1 ∗ c 0 + p 2 ∗ c 1 > p 0 ∗ c 0 + p 1 ∗ c 1 + p 2 ∗ c 1 p0*c0+p1*c0+p2*c1>p0*c0+p1*c1+p2*c1 p0c0+p1c0+p2c1>p0c0+p1c1+p2c1

则合并即可

最后对应相乘就是答案,别忘了取模 1 0 9 + 7 10^9+7 109+7

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int maxn = 3e5 + 5;
const ll inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
void dfs(int now, int fa, vector<vector<int>> &edge, vector<ll> &c,
         vector<ll> &sz, int n) {
    sz[now] = 1;
    for (auto &it : edge[now]) {
        if (it == fa) continue;
        dfs(it, now, edge, c, sz, n);
        sz[now] += sz[it];
    }
    c.emplace_back(sz[now] * (n - sz[now]));
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;
        vector<vector<int>> edge(n + 1, vector<int>());
        for (int i = 1, u, v; i < n; ++i) {
            cin >> u >> v;
            edge[u].emplace_back(v);
            edge[v].emplace_back(u);
        }
        int m;
        cin >> m;
        deque<ll> dq(m);
        for (auto &it : dq) cin >> it;
        sort(all(dq), greater<ll>());
        while (dq.size() > n - 1) {
            dq[1] = dq[0] * dq[1] % mod;
            dq.pop_front();
        }
        while (dq.size() < n - 1) dq.push_back(1);
        vector<ll> c, sz(n + 1);
        dfs(1, 0, edge, c, sz, n);
        sort(all(c), greater<ll>());
        ll ans = 0;
        for (int i = 0; i < n - 1; ++i) {
            ans = (ans + c[i] * dq[i] % mod) % mod;
        }
        cout << ans << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值