bzoj5250 [九省联考2018]秘密袭击coat 树形dp
Posted nan-cheng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj5250 [九省联考2018]秘密袭击coat 树形dp相关的知识,希望对你有一定的参考价值。
题目背景
We could have had it all. . . . . .
我们本该,拥有一切
Counting on a tree. . . . . .
何至于此,数数树上
Counting on a Tree( CoaT)即是本题的英文名称。
题目描述
AccessGlobe最近正在玩一款战略游戏。在游戏中,他操控的角色是一名C国士兵。他的任务就是服从指挥官的指令
参加战斗,并在战斗中取胜。C国即将向D国发动一场秘密袭击。作战计划是这样的:选择D国的s个城市,派出C国
战绩最高的s个士兵分别秘密潜入这些城市。每个城市都有一个危险程度di,C国指挥官会派遣战绩最高的士兵潜入
所选择的城市中危险程度最高的城市,派遣战绩第二高的士兵潜入所选择的城市中危险程度次高的城市,以此类推
(即派遣战绩第i高的士兵潜入所选择城市中危险程度第i高的城市)。D国有n个城市,n-1条双向道路连接着这些
城市,使得这些城市两两之间都可以互相到达。为了任务执行顺利,C国选出的s个城市中,任意两个所选的城市,
都可以不经过未被选择的城市互相到达。AccessGlobe操控的士兵的战绩是第k高,他希望能估计出最终自己潜入的
城市的危险程度。AccessGlobe假设C国是以等概率选出任意满足条件的城市集合S,他希望你帮他求出所有可能的
城市集合中,AccessGlobe操控的士兵潜入城市的危险程度之和。如果选择的城市不足k个,那么AccessGlobe不会
被派出,这种情况下危险程度为0。当然,你并不想帮他解决这个问题,你也不打算告诉他这个值除以998,244,353
的余数,你只打算告诉他这个值除以64,123的余数。
Input
第1行包含3个整数n、k、W
表示D国城市的个数、AccessGlobe所操控士兵潜入的城市战绩排名以及D国的所有城市中最大的危险程度;
第2行包含n个1到W之间的整数d1,d2,...,dn,表示每个城市的危险程度;
第3行到第n+1行,每行两个整数xi,yi,表示D国存在一条连接城市xi和城市yi的双向道路
1 ≤ k ≤ n,, 1 ≤ di ≤ W, n, k, W ≤ 1, 666。
Output
输出一个整数,表示所有可行的城市集合中
AccessGlobe操控的士兵潜入城市的危险程度之和除以64,123的余数。
题解参考https://cnyali-lk.blog.luogu.org/solution-p4365
这题其实正解是拉格朗日插值,结果我太菜了看不懂…啊留个坑把??
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=64123;
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
int k,W,n;
int f[2010][5010];
int w[2010],ok[maxn];
int d[maxn];
int head[maxn],cnt;
struct edge{int to,nxt;}e[maxn*2];
void add(int x,int y){
e[++cnt]=(edge){y,head[x]};
head[x]=cnt;
}
void dfs(int x,int fa){
w[x]=ok[x];
for(int i=0;i<=k;i++)f[x][i]=0;
f[x][ok[x]]=1;
for(int i=head[x];i;i=e[i].nxt){
int u=e[i].to;
if(u==fa)continue;
dfs(u,x);
for(int j=w[x];j>=0;j--){
int tmp=f[x][j];//这个在更新时会改变,所以要特别记录
for(int q=w[u];q>=0;q--)
f[x][min(j+q,k)]=(f[x][min(j+q,k)]+tmp*f[u][q])%mod;
}
w[x]=min(w[x]+w[u],k);
}
}
#undef int
int main()
#define int long long
{
n=read();k=read();W=read();
for(int i=1;i<=n;i++)d[i]=read();
for(int i=1;i<n;i++){
int u=read(),v=read();
add(u,v);add(v,u);
}
int ans=0;
for(int w=1;w<=W;w++){
int cnt=0;
for(int i=1;i<=n;i++)cnt+=(ok[i]=d[i]>=w);
if(cnt<k)break;
dfs(1,0);
for(int i=1;i<=n;i++) ans=(ans+f[i][k])%mod;
}
printf("%lld
",ans);
return 0;
}
以上是关于bzoj5250 [九省联考2018]秘密袭击coat 树形dp的主要内容,如果未能解决你的问题,请参考以下文章