农场主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. A - 卿学姐与公主(线段树+单点更新+区间极值)

    A - 卿学姐与公主 Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submi ...

  2. bootstrap中的横的列

    col-md-6都是可以嵌套的,所以12列都是虚拟的 所以bootstrap是怎么完成的?都是通过绝对的像素值吗?还是自动计算出了本区域的像素数,然后设置的? 看样子应该是后者,所以整个bootstr ...

  3. 微信小程序获得微信头像和昵称

    微信小程序之登录态的探索 { wx.getSetting({ success: res => { if (res.authSetting && res.authSetting[' ...

  4. Dire Wolf——HDU5115(区间DP)

    题意 就是有一对狼,每个狼有初始的攻击力,并且还能给左右两边的狼提供攻击力加成,当冒险家杀死一头狼的时候他也会受到这个狼目前攻击力的伤害 实例解析 33 5 78 2 0 有三头狼,刚开始第二头狼给他 ...

  5. MySQL时间戳加减转日期

    一.时间戳计算前N天后N天并转化为日期,本例是将某个时间戳转为日期,并计算出与该日期前后相差7天的日期: , , , DAY)as 'after'; 输出: # before, now, after ...

  6. luogu P5340 [TJOI2019]大中锋的游乐场

    传送门 要求经过路径汉堡的点和可乐的点个数之差绝对值\(\le k\),所以可以考虑dp,\(f_{i,j}\)表示到点\(i\),汉堡的点个数减可乐的点的个数为\(j\)的最短距离,注意一下负下标处 ...

  7. pythonr-内置函数

    pythonr-内置函数 all print (all([1,-5,3])) print (all([0,-5,3])) 如果有0 就不为真,非0就是为真 打印结果 True Flase all pr ...

  8. 一、JsonTree

    一.JsonTree [ {"id":"4","pid":"1","name":"大家电& ...

  9. [转]0day零距离

    前言: 想起这个话题,还要从早年网上的一则新闻说起--"美国联邦官员于2001年12月11日宣布,已破获一起以因特网为犯罪手段的特大软件盗版案--盗版软件的总价值至少高达10亿美元.据悉,该 ...

  10. pull request的使用

    在git中,不少开发者对自己的提升非常看重,github中的开源项目就是一个非常好的学习资料. github中的开源项目并不是完全正确的,而成为项目贡献者是一件值得骄傲的事情. 所以如何才能对开源项目 ...