2019CCPC湖南全国邀请赛(广东省赛、江苏省赛)(B - Build Tree)(找规律)

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=0Nd(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(2k200000,2p1015)

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;
}

猜你喜欢

转载自blog.csdn.net/weixin_42856843/article/details/104908063