树的数量

题目其实挺简单的,难点在于状态的设计(其实也没多难)。

令 \(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;
}

[SCOI2015]小凸玩密室

个人觉得这题非常神秘。

根据题目可知每次访问操作是访问完自己的子树,再访问父亲。所以除了第一次任意选点,剩下的都是从某个叶子节点跳到它的一个祖先或者往它的某棵子树跳。显然一颗子树对于后面的影响在于遍历完这颗子树后停在了哪里。

令 \(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杂题选做的更多相关文章

  1. 贪心/构造/DP 杂题选做Ⅱ

    由于换了台电脑,而我的贪心 & 构造能力依然很拉跨,所以决定再开一个坑( 前传: 贪心/构造/DP 杂题选做 u1s1 我预感还有Ⅲ(欸,这不是我在多项式Ⅱ中说过的原话吗) 24. P5912 ...

  2. 贪心/构造/DP 杂题选做Ⅲ

    颓!颓!颓!(bushi 前传: 贪心/构造/DP 杂题选做 贪心/构造/DP 杂题选做Ⅱ 51. CF758E Broken Tree 讲个笑话,这道题是 11.3 模拟赛的 T2,模拟赛里那道题的 ...

  3. 贪心/构造/DP 杂题选做

    本博客将会收录一些贪心/构造的我认为较有价值的题目,这样可以有效的避免日后碰到 P7115 或者 P7915 这样的题就束手无策进而垫底的情况/dk 某些题目虽然跟贪心关系不大,但是在 CF 上有个 ...

  4. 期望dp好题选做

    前言: 最近连考两场期望dp的题目,sir说十分板子的题目我竟然一点也不会,而且讲过以后也觉得很不可改.于是开个坑. 1.晚测10 T2 大佬(kat) 明明有\(O(mlog)\)的写法,但是\(m ...

  5. dp杂题(根据个人进度选更)

    ----19.7.30 今天又开了一个新专题,dp杂题,我依旧按照之前一样,这一个专题更在一起,根据个人进度选更题目; dp就是动态规划,本人认为,动态规划的核心就是dp状态的设立以及dp转移方程的推 ...

  6. 正睿OI DAY3 杂题选讲

    正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n ...

  7. 2019暑期金华集训 Day6 杂题选讲

    自闭集训 Day6 杂题选讲 CF round 469 E 发现一个数不可能取两次,因为1,1不如1,2. 发现不可能选一个数的正负,因为1,-1不如1,-2. hihoCoder挑战赛29 D 设\ ...

  8. Atcoder 水题选做

    为什么是水题选做呢?因为我只会水题啊 ( 为什么是$Atcoder$呢?因为暑假学长来讲课的时候讲了三件事:不要用洛谷,不要用dev-c++,不要用单步调试.$bzoj$太难了,$Topcoder$整 ...

  9. [SDOI2016]部分题选做

    听说SDOI蛮简单的,但是SD蛮强的.. 之所以是选做,是因为自己某些知识水平还不到位,而且目前联赛在即,不好花时间去学sa啊之类的.. bzoj4513储能表&bzoj4514数字配对 已写 ...

  10. 【做题记录】DP 杂题

    P2577 [ZJOI2004]午餐 $\texttt{solution}$ 想到贪心: 吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 状态: \(f[i][j]\) 表示前 \(i\ ...

随机推荐

  1. 前端复习之Ajax,忘完了

    1 * Day01: 2 * Ajax 3 * Asynchronous JavaScript and XML 4 * 直译中文 - JavaScript和XML的异步 5 * (不严格的定义)客户端 ...

  2. 第3章---数据探索(python数据挖掘)

    1.缺失值分析及箱型图 数据:catering_sale.xls(餐饮日销额数) 缺失值使用函数:describe()函数,能算出数据集的八个统计量 import pandas as pd cater ...

  3. 通过右键菜单生成pyd

    批处理 @echo off reg add "HKCR\AllFilesystemObjects\shell\构建PYTHON\command" /ve /t REG_SZ /d ...

  4. BLE目录

    CH58x/CH57x 蓝牙从机篇(Peripheral) CH573 CH582 CH579蓝牙从机(Peripheral)/主机(Central)例程讲解一(蓝牙主从机收发数据接口说明) CH57 ...

  5. Oracle入门- 数据库操作相关脚本

    1. 创建表 1 CREATE TABLE SYS_NOTICE 2 ( 3 GUID CHAR(32) NOT NULL, 4 TITLE VARCHAR2(128) NOT NULL 5 ); 6 ...

  6. android装包

    一.找到对应包体apk 二.数据线连接电脑及手机,弹出USB连接选项并选择传输文件 注:如果未弹出USB连接选项可尝试换根数据线解决 三.点击我的电脑找到本机设备 四.将对应包体文件拖入本机设备 五. ...

  7. Go_day03

    Go基础语法 数组 数组是具有相同唯一类型的一组以编号且长度固定的数据项序列.类型可以是任意基本类型或者自定义类型. 数组一旦被定义后,大小不能被改变 func main() { //定义一个数组 v ...

  8. webpack之性能优化(webpack4)

    在讲解性能优化的方案之前,我们需要了解一下webpack的整个工作流程, 方案一:减少模块解析 也就是省略了构建chunk依赖模块的这几个步骤 如果没有loader对该模块进行处理,该模块的源码就是最 ...

  9. GPU Skinning

    这个工具的作用是同一种角色在同屏里面出现一大堆时,可以大幅度的降低DrawCall.我试了一下,感觉挺有意思的,各位可以试试.它的原理实际上是把骨骼矩阵存在配置文件里面,然后通过特殊的shader,计 ...

  10. Why WebRTC|“浅入深出”的工作原理详解

    前言 近几年实时音视频通信应用呈现出了大爆发的趋势.在这些实时通信技术的背后,有一项不得不提的技术--WebRTC. 今年 1 月,WebRTC 被 W3C 和 IETF 发布为正式标准.据调研机构 ...