dp杂题选做
题目其实挺简单的,难点在于状态的设计(其实也没多难)。
令 \(f_i\) 表示 \(i\) 个点的 \(m\) 叉树的数量,发现无法转移。设 \(g_{i,j}\) 表示根节点所在子树内有 \(i\) 个节点,\(j\) 个儿子(儿子所在子树可以为空)。可以写出转移方程:\(g_{i,j}=\sum\limits_{k=0}^{i-1} g_{i-k,j-1}\times f_k\),\(f_i=g_{i,m}\)
点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int N=200,mod=1e4+7;
int n,m,f[N][N];
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
read(n),read(m);
for(int i=0;i<=m;i++){
f[1][i]=f[0][i]=1;
}
for(int i=2;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=0;k<i;k++){
f[i][j]=(f[i][j]+f[i-k][j-1]*f[k][m]%mod)%mod;
}
}
}
write_endl(f[n][m]);
return 0;
}
个人觉得这题非常神秘。
根据题目可知每次访问操作是访问完自己的子树,再访问父亲。所以除了第一次任意选点,剩下的都是从某个叶子节点跳到它的一个祖先或者往它的某棵子树跳。显然一颗子树对于后面的影响在于遍历完这颗子树后停在了哪里。
令 \(f_{u,x}\) 表示从根开始,访问完以 \(u\) 为根的子树后停在 \(x\) 处的最小费用,\(ls/rs\) 表示左/右儿子。分类讨论可以得到长得极为对称的两个转移方程
当 \(x\) 在左子树,\(f_{u,y}=\min\{dis(u,ls)\times a_{ls}+f_{ls,x}+dis(x,rs)\times a_{rs}+f_{rs,y}\}\)
当 \(x\) 在右子树,\(f_{u,y}=\min\{dis(u,rs)\times a_{rs}+f_{rs,x}+dis(x,ls)\times a_{ls}+f_{ls,y}\}\)
这个方程的复杂度接近 \(O(n^2)\),显然不能接受。
拆开式子,\(dis(x,rs)=dis(u,rs)+dis(x,u)\),发现只有 \(dis(x,u)\) 是个影响答案的关键信息,将它记录下来。
但因为没有要求从 \(1\) 开始,所以定义另一个状态 \(g_{u,x}\) 表示访问完以 \(u\) 为根的子树后停在 \(x\) 处的最小费用。继续分类讨论
当 \(x\) 在左子树,\(g_{u,y}=\min\{f_{u,y},f_{ls,x}+dis(x,u)\times a_u+dis(rs,u)\times a_{rs}+f_{rs,y}\}\)
当 \(x\) 在右子树,\(g_{u,y}=\min\{f_{u,y},f_{rs,x}+dis(x,u)\times a_u+dis(ls,u)\times a_{ls}+f_{ls,y}\}\),最后从所有 \(g_{1,x}\) 中取最小值即可。
点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int N=2e5+10,inf=1e18;
int dis[N],n,a[N],b[N];
vector<int>d[N],f[N],g[N];
int ls(int p){
return p<<1;
}
int rs(int p){
return p<<1|1;
}
int fa(int p){
return p>>1;
}
void dfs(int u){
dis[u]=dis[fa(u)]+b[u];
if(ls(u)<=n){
dfs(ls(u));
int s=f[ls(u)].size();
if(rs(u)<=n){
dfs(rs(u));
int ans1=inf,ans2=inf,ansp1=inf,ansp2=inf;
for(int i=0;i<f[u].size();i++){
if(i<s){
ans1=min(ans1,f[ls(u)][i]+b[ls(u)]*a[ls(u)]+(d[u][i]+b[rs(u)])*a[rs(u)]);
ansp1=min(ansp1,g[ls(u)][i]+d[u][i]*a[u]+b[rs(u)]*a[rs(u)]);
}
else{
ans2=min(ans2,f[rs(u)][i-s]+b[rs(u)]*a[rs(u)]+(d[u][i]+b[ls(u)])*a[ls(u)]);
ansp2=min(ansp2,g[rs(u)][i-s]+d[u][i]*a[u]+b[ls(u)]*a[ls(u)]);
}
}
for(int i=0;i<f[u].size();i++){
if(i<s){
f[u][i]=ans2+f[ls(u)][i];
g[u][i]=min(f[u][i],ansp2+f[ls(u)][i]);
}
else{
f[u][i]=ans1+f[rs(u)][i-s];
g[u][i]=min(f[u][i],ansp1+f[rs(u)][i-s]);
}
}
}
else{
for(int i=u;i>=1;i/=2){
f[i].pb(0);
g[i].pb(0);
d[i].pb(dis[u]-dis[i]);
}
f[u][0]=b[ls(u)]*a[ls(u)];
g[u][0]=inf;
f[u][1]=inf;
g[u][1]=b[ls(u)]*a[u];
}
}
else{
for(int i=u;i>=1;i/=2){
f[i].pb(0);
g[i].pb(0);
d[i].pb(dis[u]-dis[i]);
}
}
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
read(n);
for(int i=1;i<=n;i++){
read(a[i]);
}
for(int i=2;i<=n;i++){
read(b[i]);
}
dfs(1);
int ans=inf;
for(int i=0;i<g[1].size();i++){
ans=min(ans,g[1][i]);
}
write_endl(ans);
return 0;
}
dp杂题选做的更多相关文章
- 贪心/构造/DP 杂题选做Ⅱ
由于换了台电脑,而我的贪心 & 构造能力依然很拉跨,所以决定再开一个坑( 前传: 贪心/构造/DP 杂题选做 u1s1 我预感还有Ⅲ(欸,这不是我在多项式Ⅱ中说过的原话吗) 24. P5912 ...
- 贪心/构造/DP 杂题选做Ⅲ
颓!颓!颓!(bushi 前传: 贪心/构造/DP 杂题选做 贪心/构造/DP 杂题选做Ⅱ 51. CF758E Broken Tree 讲个笑话,这道题是 11.3 模拟赛的 T2,模拟赛里那道题的 ...
- 贪心/构造/DP 杂题选做
本博客将会收录一些贪心/构造的我认为较有价值的题目,这样可以有效的避免日后碰到 P7115 或者 P7915 这样的题就束手无策进而垫底的情况/dk 某些题目虽然跟贪心关系不大,但是在 CF 上有个 ...
- 期望dp好题选做
前言: 最近连考两场期望dp的题目,sir说十分板子的题目我竟然一点也不会,而且讲过以后也觉得很不可改.于是开个坑. 1.晚测10 T2 大佬(kat) 明明有\(O(mlog)\)的写法,但是\(m ...
- dp杂题(根据个人进度选更)
----19.7.30 今天又开了一个新专题,dp杂题,我依旧按照之前一样,这一个专题更在一起,根据个人进度选更题目; dp就是动态规划,本人认为,动态规划的核心就是dp状态的设立以及dp转移方程的推 ...
- 正睿OI DAY3 杂题选讲
正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n ...
- 2019暑期金华集训 Day6 杂题选讲
自闭集训 Day6 杂题选讲 CF round 469 E 发现一个数不可能取两次,因为1,1不如1,2. 发现不可能选一个数的正负,因为1,-1不如1,-2. hihoCoder挑战赛29 D 设\ ...
- Atcoder 水题选做
为什么是水题选做呢?因为我只会水题啊 ( 为什么是$Atcoder$呢?因为暑假学长来讲课的时候讲了三件事:不要用洛谷,不要用dev-c++,不要用单步调试.$bzoj$太难了,$Topcoder$整 ...
- [SDOI2016]部分题选做
听说SDOI蛮简单的,但是SD蛮强的.. 之所以是选做,是因为自己某些知识水平还不到位,而且目前联赛在即,不好花时间去学sa啊之类的.. bzoj4513储能表&bzoj4514数字配对 已写 ...
- 【做题记录】DP 杂题
P2577 [ZJOI2004]午餐 $\texttt{solution}$ 想到贪心: 吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 状态: \(f[i][j]\) 表示前 \(i\ ...
随机推荐
- java: javacTask: 源发行版 8 需要目标发行版 1.8
idea同一工作空间中不同工程使用不同的jkd版本.在本地idea同时使用jdk1.7和jdk1.8,不同的java工程使用不同的jdk版本,但是在java代码编译时报错,其报错信息为:[java: ...
- springboot后端接收不到前端传来的表单值
为啥接收不到 因为传来的字段值太大了,springboot默认启动依赖tomcat,tomcat默认接收表单值最大为2MB,将server.tomcat.max-http-form-post-size ...
- JAVA获取MultipartFile文件的MD5
Java获取文件的MD5,核心都是通过JAVA自带的MessageDigest类来实现. 获取文件MD5值主要分为三个步骤: 第一步获取文件的byte信息, 第二步通过MessageDigest类进行 ...
- zabbix 告警说明及触发cpu告警
1. https://www.cnblogs.com/caonw/p/12766454.html 1.内存检测:Template OS Linux:vm.memory.size[available]. ...
- jmeter--操作
Jmeter响应断言--正则表达式判断纯数字 这样是匹配14位数字,如果响应是纯数字可以直接用上 jmeter 随机取一个值的方法 1.添加用户自定义变量 在要用到随机值的地方写入 ${__Ran ...
- mysql 的存储过程
定义不带参数的存储过程 CREATE PROCEDURE s1() BEGINselect * from ecs_admin_action;End call s1; 2.带输入参数的 create P ...
- Java-02对象传递和返回
Java-02对象传递和返回 当你在"传递"一个对象的时候,你实际上是在传递它的引用 1引用 1.1传递引用 当你将一个引用传给方法后,该引用指向的仍然是原来的对象: /** * ...
- Winhex 恢复三个分区
通过之前的博客WinHex恢复分区,我们知道 在MBR中,一共有四行是我们分区的引导,所以,我们手动只能创建三个主分区,通过工具软件,我们最多可以创建四个主分区 那么测试:如何创建四个主分区? 首先, ...
- 归一化,正则化,标准化,dropout的联系与区别
归一化(Normalization)是指将数据缩放到一定范围内,一般是将数据映射到[0,1]或[-1,1]之间.这样可以避免不同特征的数值差异过大而导致的训练困难,同时也有助于加快梯度下降的收敛速度. ...
- 自己动手从零写桌面操作系统GrapeOS系列教程——12.QEMU+GDB调试
学习操作系统原理最好的方法是自己写一个简单的操作系统. 写程序不免需要调试,写不同的程序调试方式也不同.如果做应用软件开发,相应的程序调试方式是建立在有操作系统支持的基础上的.而我们现在是要开发操作系 ...