2019CCPC湖南全國邀請賽(廣東省賽、江蘇省賽)(B - Build Tree)(找規律)
Time limit1500 ms
Memory limit65536 kB
Description
You need to construct a full -ary tree(n叉樹) with layers.All the edges in this tree have a weight.But this weight cannot be chosen arbitrarily you can only choose from set ,the size of is ,each element in the set can only be used once.Node 0 is the root of tree.
We use for the distance from root to node .Our goal is to minimize the following expression:
Please find the minimum value of this expression and output it.Because it may be a big number,you should output the answer modul .
Input
The input file contains 2 lines.
The first line contains 4 integers,these respectively is
The second line contains integers,represent the set S,the elements in the set guarantee less than or equal to .
We guarantee that 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;
}