2019CCPC湖南全国邀请赛(广东省赛、江苏省赛)(B - Build Tree)(找规律)
Time limit1500 ms
Memory limit65536 kB
Description
You need to construct a full n n n-ary tree(n叉树) with m m m layers.All the edges in this tree have a weight.But this weight cannot be chosen arbitrarily you can only choose from set S S S,the size of S S S is k k k,each element in the set can only be used once.Node 0 is the root of tree.
We use d ( i ) d(i) d(i) for the distance from root to node i i i.Our goal is to minimize the following expression:
m i n ∑ i = 0 N d ( i ) min∑_{i=0}^N{d(i)} mini=0∑Nd(i)
Please find the minimum value of this expression and output it.Because it may be a big number,you should output the answer modul p p p.
Input
The input file contains 2 lines.
The first line contains 4 integers,these respectively is k , m , n , p 。 ( 2 ≤ k ≤ 200000 , 2 ≤ p ≤ 1 0 15 ) k,m,n,p。(2 ≤ k ≤200000,2 ≤ p≤ 10^{15}) k,m,n,p。(2≤k≤200000,2≤p≤1015)
The second line contains k k k integers,represent the set S,the elements in the set guarantee less than or equal to 1 0 15 10^{15} 1015.
We guarantee that k k k is greater than or equal to the number of edges.
Output
The output file contains an integer.represent the answer.
Sample Input
5 2 3 10
1 2 3 4 5
Sample Output
6
题意
给你一个序列,长度为k,让你利用这些值当作边的权值建立一颗m层的满n叉树,每个点到根节点的距离是路径的权值之和,然后问你每一个边到根节点的距离之和。
本来就是一道规 (S) 律 (B) 题,可是明明思路很清楚,却总不知道怎么敲下那代码,于是就有了这篇整理。
题解
一切尽在图中
代码
#include <bits/stdc++.h>
#define maxn 200005
#define _for(i, a) for(int i = 0; i < (a); ++i)
using namespace std;
typedef long long LL;
LL n, m, k, p;
LL a[maxn];
LL ans;
LL num[maxn];
void init() {
ans = 0;
num[0] = 0;
num[1] = 0;
for (LL i = 2, t = n; i <= m; ++i, t *= n) num[i] = num[i - 1] + t, num[i] %= p;
}
void sol() {
init();
_for(i, k) scanf("%lld", &a[i]);
sort(a, a + k);
for (int i = 1; i < k; ++i) a[i] += a[i - 1], a[i] %= p;
if (m == 1) ans = 0;
else {
for (LL i = 2; i <= m; ++i) {
LL _sum = a[num[i] - 1] + p - (i == 2 ? 0 : a[num[i - 1] - 1]); _sum %= p;
LL times = (num[m - i + 1] + 1) % p;
ans += _sum * times, ans %= p;
}
}
cout << ans << "\n";
}
int main() {
while (cin >> k >> m >> n >> p) {
sol();
}
return 0;
}