0%

CF-1072-D. Unfair Game(记忆化搜索就是要搜索所有可能要转移到这个状态的状态)

题目大意

Bob 想了一个 1 到 n 之间的数字(n = 2^d)。Alice 初始知道这个数字是奇数还是偶数。

Alice 每回合可以选择:

  • 将当前数字除以 2(仅当数字为偶数时)

  • 将当前数字减 1

每次操作后,Bob 会告诉 Alice 一个非负整数 x,表示当前数字 a 能被 2^x 整除,但不能被 2^(x+1) 整除。如果数字变为 0,Alice 获胜。

游戏最多进行 k 回合。求有多少个初始数字(1 到 n)使得 Alice 在最优策略下无法在 k 回合内获胜。

ABC-387-C - Snake Numbers 

HDU - 2089- 不要62

思路讲解

在题目要求下,一个数字要删多少次有规律吗?其实就是 popcount(x)+log2(x)\text{popcount}(x)+\lfloor\log_{2}(x)\rfloor

然后问题就来到了这个怎么样快速统计了,这个是这道题目的难点。当然,显然我们应该使用这个数位 dp。

那么我们一般数位 dp 采用的是这个记忆化搜索,我们定义搜索递归函数为 dfs(len,limit)dfs(len,limit)dplen,limit,valdp_{len,limit,val} 表示在 $len $ 长度下,limitlimit 受或不受 nn 高位限制的情况下,数字所需消耗次数为 valval 的数有几个。

然后我们来想一想,就是这个普通搜索,我们要知道 dfs(len,limit)dfs(len,limit) 的结果,进入到 dfs(len,limit)dfs(len,limit) 之后,我们需要搜什么?显然,我们需要搜索 dfs(len1,?)dfs(l,?)dfs(0,?)dfs(len-1,?)\cdots dfs(l,?)\cdots dfs(0,?),因为我们要搜索所有可能会转移到这个状态的状态

从状态 llenl\to len,那么会增加多少消耗次数呢?Δlenl+1\Delta \gets len-l+1(长度增加 lenllen-l,还增加了一个 1)。

⚠️ 注意:从 0 转移过来的特殊情况Δlenl\Delta \gets len-l,如果你像我一样认为 0 的二进制长度为 1 的话(这个是因为,我们虽然认为 0 的二进制长度为 0,但是实际上我们的 lenlen 并没有增加 lenlen 的长度,只增加了 len1len-1 的长度)。

那么前面讲的有点抽象,举个例子就是(1011)2(1011)_{2} 就是从 (11)2(11)_{2} 转移过来的,因为我们的状态设计是不包含前导 0 的。当然,如果 (1011)2(1011)_{2} 就是题目中的 n 的话(即表示二进制长度为 4 的上限限制),除了 (11)2(11)_{2},还可以从 (1)2(1)_2(0)2(0)_2 转移过来,但是显然不能从 (100)2(100)_2 等二进制长度为 3 的状态转移过来。

最后统计答案的时候,需要将这个 dfs(len,1),dfs(len1,0),,dfs(0,0)dfs(len,1),dfs(len-1,0),\cdots,dfs(0,0) 的状态结果累和得到答案。

AC代码

AC
https://codeforces.com/contest/2184/submission/357806886

心路历程(WA,TLE,MLE……)

向左短路 RE 了。

image

首先,不难发现,在题目要求下,我们只能够在二进制第一个 1 出现位置进行操作,把这个 1 后面出现的所有 0 全部消除。所以说,一个数字要删多少次有规律吗?

首先,不妨定义状态,dpidp_i 指的是

当然,虽然知道了要使用数位 dp,如何实现也至少是需要想一想的。虽然说数位 dp 一般采用这个自顶向下的记忆化搜索设计方法,但是这道题目没什么限制条件,以计数为主,直接采用这个递推法即可。

dplen,idp_{len,i} 表示在该(二进制)长度下,val=ival=i 的这个数字的数量。

dplen,il=0len1dpl,i+1+lenldp_{len,i}\gets \sum_{l=0}^{len-1}dp_{l,i+1+len-l}

那么我们一般数位 dp 采用的是这个记忆化搜索,我们就先想搜索吧,搜索 [0,n][0,n] 有几个数字的 val>kval>k。当然这个有点奇怪,我们不妨假设我们是求的这个 [0,n][0,n] 下,val=ival=i 的这个数字的数量,即 dpidp_i

那我们要搜索这个东西,需要什么呢?dfs(len,ismax)dfs(len,ismax) 可以吗?我们先试试,我们首先发现,只有 dpidp_{i} 无法满足这个我们的要求,设置为 dplen,idp_{len,i} 更为合适。