农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地。John打算在牧场上的某几格里种上美味的草,供他的奶牛们享用。

遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜欢独占一块草地的感觉,于是John不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。

John想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择?(当然,把新牧场完全荒废也是一种方案)

发现数据范围很小,可以状压,那么要压什么东西?

在一个格子种了草之后其他的格子都不能种草

用f[i][s]代表前i行的草种完了,且第i行种的草的长相为d的方案数有多少

数位dp:

给定一个x,有多少个y满足0<=y<x

一位一位给每一个格子填数

从高向低填,这样方便比较大小

状态:f[i][j]表示已经从高位向低位填了i位,j=0或1,如果j=0,表示填的数已经<x,如果j=1,表示目前填的所有数都=x

初始化:f[l+1][1]=1  因为第l位之前都只能填0

转移:枚举下一位填什么

考虑自己更新别人

如果填进去数之后会导致y比x大,显然就不行了,直接不用转移

如果填进去之前j=0,那么之后不管怎么填j都只能=0

如果填进去之前j=1,只有当填的这一位和x的这一位一样的时候,j才会继续是1

f[i-1][j’]+=f[i][j]

例:求[l,r]中的数位之和

0~r的数位之和减0~l-1的数位之和

f[i][j]表示数有多少个

g[i][j]表示数字之和是多少

转移:考虑第下一位到底填什么

如果填1的话对答案的贡献是多少?由于上一位填的可能有很多种,所以1做出的贡献应该是f[i][j]*k

#include<iostream>

using namespace std;

int solve(int x)
{
int l=;
while (x>)
{
l++;
z[l] = x%;
x/=;
}
memset(f,,sizeof(f));
memset(g,,sizeof(g));
f[l+][]=;
g[l+][]=;
for (int i=l+;i>=;i--)
for (int j=;j<=;j++)
for (int k=;k<=;k++)
{
if (j== && k>z[i-]) continue;
int j_;
if (j==) j_=;
else if (k==z[i-]) j_=;
else j_=;
f[i-][j_] += f[i][j];
g[i-][j_] += f[i][j] * k + g[i][j];
}
return g[][] + g[][];
} int main()
{
cin >> l >> r;
cout << solve(r) - solve(l-) << endl; return ;
}

例:求在[l,r]中满足十进制位中相邻两个数字之差至少为2的数有多少个

f[i][j][k]表示已经填到第i位,前面是小于还是等于,第i位填的k

在填第i-1位的时候看看第i位填的是多少

windy数

例:求在[l,r]中有多少数满足各位数乘积=k

如果按照上个题的方法做,设f[i][j][k],会炸空间

因为k是很多个个位数乘起来的,所以不能出现超过10的质因子,也就是说我们开的大部分数组都是空的

设f[i][j][a][b][c][d],a,b,c,d表示2^a,3^b,5^c,7^d,a,b,c,d分别取log2 10^18 ,log3 10^18 ,log5 10^18 ,log3 10^18

但是直接做时间复杂度还是会炸,继续优化

我们发现这些如果一个数取到上界,其他就取不到上界,枚举就浪费时间了。所以直接dfs预处理出longlong内所有满足这个性质的数,直接把数组改成f[i][j][k],k表示是第k个

树形dp

顾名思义,在树上进行dp

例:求树上有多少个点(什么沙雕题)

基础思路:从下往上推,在每一个点维护他的子树的信息

f[i]:以i为根的子树有多少点,f[i]就是它所有子树的大小之和+1

例:求树的直径(在树上找到两个点使得这两个点的距离最远)

两个点之间的距离一定是一个点到他们的lca再到另一个点

可以看成是lca向下的两条路

也就是说有一个拐点。我们可以维护从每个点向下走最长和次长能走多少

用f[i][0]表示从i向下的最长路,f[i][1]表示次长路

然后枚举每一个点,对f[i][0]+f[i][1]取最大值

那么怎么算?

f[i][0]=max(f[p[j]][0])+1

f[i][1]呢?

如果我们把最长路和次长路混在一起取次长,就有可能经过同一个节点,这样就并不是一条正常的路径了

所以我们再选次长的时候,一定要避免和f[i][0]选到同一个位置去

所以我么直接把剩下的所有儿子的最长取出来取最长

#include<iostream>

using namespace std;

void dfs(int i)
{
for (p is i's son)
dfs(p); for (p is i's son)
{
int v = f[p][]+;
if (v>f[i][])
{
f[i][]=f[i][];
f[i][]=v;
}
else if (v>f[i][]) f[i][]=v;
}
} int main()
{
cin >> n;
du ru he jian shu; dfs(); return ;
}

例:求树上路径的总长度

f[i]表示以i为根的子树有多少个点,考虑每个边被算进答案多少次

2*f[i]*(n-f[i])对答案的贡献

答案就是对边求一个Σ就完了

例:没有上司的舞会

设f[i][0/1]代表以i为根的子树里面选择一些点,0代表没选,1代表选了,在这种情况下获得的最大价值

答案就是max(f[1][0],f[1][1])

如果i选了,他的所有儿子都不能选,f[i][1]=Σf[j][0](j∈son[i]) +a[i]

如果i没选,他的儿子可以选也可以不选,f[i][0]=Σmax(f[j][0],f[j][1])(j∈son[i])

例:Strategic game

和上个题差不多

如果能守护距离不超过2的点?

f[i][0/1/2]表示在i的子树被完全覆盖的情况下往下走到第一个士兵距离是0/1/2

f[i][0]=Σmin(f[j][0],f[j][1],f[j][2])+1(j∈son[i])

g[j][0/1]表示我已经确定了前j个儿子的取值,其中这j个儿子有没有拿出一个0(有士兵)作为答案

dp套dp

qbzt day5 下午的更多相关文章

  1. Day5下午解题报告1

    预计分数:100+60+30=190 实际分数:100+60+30=190 终于有一道无脑T1了哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈 ...

  2. qbzt day6 下午 模拟赛

    我太菜了 T2 给定一张有向图,每个点有点权.试找到一条路径,使得该路径上的点权最 大值减去点权最小值最大,问这个差最大是多少.   话说这个题第一个想到的思路是tarjan缩点+拓扑排序来着... ...

  3. qbzt day5 上午

    动态规划 递推  递归   记忆化搜索 斐波那契数列 1.用其他已经计算好的结果计算自己的结果(递推) 2.用自己的值计算别人的值(考虑对之后的项做出的贡献) cin >> n; f[]= ...

  4. qbzt day4 下午

    有向图的强连通分量 强联通:两个点之间可以互相到达 如果某个图任意两个点都是强联通的,那么称这个图强联通 如果一个图的子图是强联通的,那么称这个图是强联通子图 一个图的极大强联通子图被称作强连通分量 ...

  5. qbzt day3 下午(好难)

    内容提要 有关数据结构的例题 求逆序对数 统计每个数前面有多少比他大的数 开数组表示这个数之前0~9这些数出现了几次 动态将某个点加一,动态求前缀和 用树状数组 如果数太大了怎么办? 离散化 步骤:先 ...

  6. qbzt day2 下午

    内容提要 高精 矩阵 筛法 先是高精除法 注意细节 高精度开方:神奇的竖式 以小数点为分界线,每两个位砍一刀 87654.321-->08|76|54|.32|1 大概就是先对第一位开方,然后相 ...

  7. NOI2018场外游记

    鬼晓得APIO以后我经历了些什么 Day 0 好像没什么要记的 Day 1 下午去参加开幕式 神tm大型落地柜装风扇空调下放冰块 开幕式,,,hot chocolate是真的hot(强制在线?卡常?) ...

  8. 搞了我一下午竟然是web.config少写了一个点

    Safari手机版居然有个这么愚蠢的bug,浪费了我整个下午,使尽浑身解数,国内国外网站搜索解决方案,每一行代码读了又想想了又读如此不知道多少遍,想破脑袋也想不通到底哪里出了问题,结果竟然是web.c ...

  9. day5

    作业 作业需求: 模拟实现一个ATM + 购物商城程序 额度 15000或自定义 实现购物商城,买东西加入 购物车,调用信用卡接口结账 可以提现,手续费5% 每月22号出账单,每月10号为还款日,过期 ...

随机推荐

  1. C++中操作符重载的概念

    1,下面的复数解决方案是否可行? 1,代码示例: class Comples { public: int a; int b; }; int main() { Complex c1 = {, }; Co ...

  2. CentOS卸载lamp环境的步骤

    学习PHP的时候需要在CentOS系统下安装lamp环境,安装容易卸载就没那么简单了,因为lamp由Apache.MySQL.PHP三个部分构成,需要逐个卸载,小编就给大家介绍下CentOS卸载lam ...

  3. virtualenvwrapper安装和使用

    virtualenvwrapper安装和使用步骤: 1.安装: *nix上安装的命令: pip install virtualenvwrapper windows上安装的命令: pip install ...

  4. ubuntu install xsltproc docbook-xsl docbook-xml

    问题一: $ makexsltproc --output phtml/ param.xsl ./pxml/mainbook.xmlmake: xsltproc: Command not foundma ...

  5. maven多模块tomcat启动报 NoClassDefFoundError:com/test/main/message

    maven多模块tomcat启动报 NoClassDefFoundError:com/test/main/message 扫描不到 添加子模块jar包

  6. jquery遍历标签中自定义的属性方法

    在开发中我们有时会对html标签添加属性,如何遍历处理 <ul> <li name="li1" sortid="nav_1">aaaaa ...

  7. 关于ResultSet中getDate\getTime\getTimestamp的区别的记录

    getDate() 返回时间的年月日 getTime() 返回时间的时分秒 getTimestamp () 返回时间的年月日 时分秒

  8. PAT Advanced 1058 A+B in Hogwarts (20 分)

    If you are a fan of Harry Potter, you would know the world of magic has its own currency system -- a ...

  9. linux中未实现的系统调用

    afs_syscall, break, fattach, fdetach, ftime, getmsg, getpmsg, gtty, isastream, lock, madvise1, mpx, ...

  10. JVM Direct Memory

    JVM除了堆内存.栈内存,还有DirectMemory内存,DirectMemory是java nio引入的. 在JDK1.4中新加入了NIO(New INput/Output)类,引入了一种基于通道 ...