题目:Build Tree
思路:类似于哈夫曼树的贪心想法,先将消耗大的离根更近一些,当计算当前边权时,统计它下面的所有子节点数再加上它本身,就是这条边在所有子节点到根节点的路径上出现的数目
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
const int N=2e5+5;
int k, m, n;
LL p, tr[N];
LL ans;
LL cal(int x){
LL res=0;
LL mul=1;
for(int i=1; i<=m-(x+1); i++)
{
mul*=n;
res+=mul;
}
return res+1;
}
void dfs(int cnt, int st){
if(cnt>=m) return ;
for(int i=st; i<=st+pow(n,cnt)-1; i++)
ans=(ans+tr[i]*cal(cnt)%p)%p;
dfs(cnt+1, st+pow(n,cnt));
}
int main(){
while(~scanf("%d%d%d%lld",&k, &m, &n, &p)){
ans=0;
for(int i=1; i<=k ;i++) scanf("%lld",&tr[i]);
sort(tr+1, tr+k+1);
dfs(1, 1);
printf("%lld\n",ans);
}
return 0;
}