[HDU4734] F(x)(数位dp+优化)

>传送门<
题意:对于一个有n位(这n位从高位到低位分别是AnAn-1An-2 ... A2A1)的十进制数,我们定义它的权值F(x)=An*2n-1 + An-1*2n-2 + ... + A2*2 + A1*1.现在给你两个数AB,请计算[0,B]范围内有多少个权值<=F(A)的数

思路:(这个下面文字是有点多,可能是我太弱了,在刚开始学的时候只有这样我才能理解QAQ~)

其实F(x)只是给每一个数位带上一个权值v = 2^(p-1)F(x)最大是值不会超过5000,我们完全可以抛开权值来思考,写代码的时候再加上权值即可,这样思考和写草稿之类的会方便很多,不考虑每一位的权值的话即是数位的前缀和。

很容易想到一个dp式是dp[pos][sum];表示当前在第pos位,前缀和为sum的答案,快速把数位dp敲完,交上去,然后会发现TLE掉了,这题的时限只有500ms,TLE的原因是什么呢,就是记忆化不够彻底

在做数位dp入门题 不要62 的时候可能有点人会注意,dp数组只需要初始化一次即可,这是因为不要62题意中是不包含4和连续的62的数的个数,这里的条件是一个数本身的性质,也就是说,一个数有没有4或者连续的62和你输入的[l,r]区间是无关的,比如1234是不合法的,无论你输入1 - 1000 还是 1 - 10000,1234都是不合法的。

但是这里是不一样的,题意要求小于F(a),而a是输入的,而dp数组定义是:dp[pos][sum],表示当前在第pos位,前缀和为sum的答案, 如假设上限是55555, 那么123xxx 和 321xxx 的答案都是 dp[3][6] ,这就是记忆化的结果,因为我不需要考虑前面具体的数的123 还是321 114之类的,只要他们的前缀和sum相同并且在同样的数位,后面xxx的情况都是一样的,因为后面的约束条件都是和不大于F(a)-sum。

问题就是在这个地方,由于我的记忆化是和输入的a也就是F(a)有关,所以我不能把它当作一个数的性质来记忆话,比如同样是123xxx,对于F(a) = 10F(a) = 20,后面xxx可行的情况是不一样的,a=10的时候,后面的约束是不大于F(a)-sum = 4a = 20的时候约束为不大于F(a)-sum = 14,从而导致了每次输入不同的a都要重新初始化dp数组,重新搜索一次。这里可以通过对dp状态的定义做一点小小的改变,使得约束条件变为与F(a)无关,从而不需要每次初始化重新搜索,定义dp[pos][sum],表示当前在第pos位,F(a)-sum的答案sum为到第pos位为止的数位前缀和),这时在第pos位的约束条件是后面所有的数的和不大于sum这时记忆化的是sum,是与F(a)无关的,比如当F(a) = 10F(a) = 20时,F(a) = 10时,123xxx、321xxx等对应的是dp[3][4] F(a)=20时,556xxx、466xxx对应的也是dp[3][4],因为2种情况的posF(a)-sum都是相同的,所以记忆化一次即可,不必初始化

猜你喜欢

转载自www.cnblogs.com/wizarderror/p/11347119.html
今日推荐