>传送门<
题意:对于一个有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都是相同的,所以记忆化一次即可,不必初始化

总结一下,在设计数位dp状态时最好把每次询问的变量作为初始值而不是状态转移、判定时依赖的量(比如第一个状态判定条件是F(x)<=F(a),就依赖于当前F(a),这样就不好),这样才可以最大限度的发挥记忆化的作用。

 Code

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e4+5; int A, B, t, tot;
int a[12], dp[12][maxn];
int f(int x) {
int ans = 0, cnt = 0;
while(x){
ans += (x%10)*(1<<(cnt++));
x /= 10;
}
return ans;
}
int dfs(int pos, int sum, int limit) {
if(pos==0) return sum<=tot;
if(sum>tot) return 0;
if(!limit&&dp[pos][tot-sum]!=-1) return dp[pos][tot-sum];
int up = limit?a[pos]:9;
int ans = 0;
for(int i = 0; i <= up; i++)
ans += dfs(pos-1, sum+i*(1<<(pos-1)), limit&&i==a[pos]);
if(!limit) dp[pos][tot-sum] = ans;
return ans;
}
int solve(int x) {
int pos = 1;
while(x) {
a[pos++] = x%10;
x /= 10;
}
return dfs(pos-1, 0, 1);
}
int main()
{
int kase = 1;
memset(dp,-1,sizeof dp);
scanf("%d", &t);
while(t--) {
scanf("%d%d", &A, &B);
tot = f(A);
printf("Case #%d: %d\n", kase++, solve(B));
}
return 0;
}

参考文章:

https://www.cnblogs.com/AbandonZHANG/p/4114122.html

http://www.bubuko.com/infodetail-2320548.html

https://blog.csdn.net/wust_zzwh/article/details/52100392

https://www.cnblogs.com/herumw/p/9464514.html

[HDU4734] F(x)(数位dp+优化)的更多相关文章

  1. [hdu4734]F(x)数位dp

    题意:求0~f(b)中,有几个小于等于 f(a)的. 解题关键:数位dp #include<bits/stdc++.h> using namespace std; typedef long ...

  2. hdu4734 F(x)(数位dp)

    题目传送门 F(x) Time Limit: 1000/500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  3. HDU-4734 F(x) 数位DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4734 注意到F(x)的值比较小,所以可以先预处理所有F(x)的组合个数.f[i][j]表示 i 位数时 ...

  4. 【hdu4734】F(x) 数位dp

    题目描述 对于一个非负整数 $x=​​\overline{a_na_{n-1}...a_2a_1}$ ,设 $F(x)=a_n·2^{n-1}+a_{n-1}·2^{n-2}+...+a_2·2^1+ ...

  5. hdoj4734(数位dp优化)

    题目链接:https://vjudge.net/problem/HDU-4734 题意:定义一个十进制数AnAn-1...A1的value为An*2n-1+...+A1*20,T组样例(<=1e ...

  6. hdu 4389 X mod f(x) 数位DP

    思路: 每次枚举数字和也就是取模的f(x),这样方便计算. 其他就是基本的数位Dp了. 代码如下: #include<iostream> #include<stdio.h> # ...

  7. HDU 4734 F(x) ★(数位DP)

    题意 一个整数 (AnAn-1An-2 ... A2A1), 定义 F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1,求[0..B]内有多少 ...

  8. hdu 4734 F(x)(数位dp+优化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4734 题意:我们定义十进制数x的权值为f(x) = a(n)*2^(n-1)+a(n-1)*2(n-2 ...

  9. HDU 4734 - F(x) - [数位DP][memset优化]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4734 Time Limit: 1000/500 MS (Java/Others) Memory Lim ...

随机推荐

  1. 如何限制电脑访问网址—使用Host限制访问网址

    如何限制电脑访问网址-使用Host限制访问网址 1. 打开C:\Windows\System32\drivers\etc 2. 打开hosts 3. 修改host内容,如下示例 127.0.0.1  ...

  2. 7.shell脚本编程

    1.shell 脚本语言的基本用法 1.1shell 脚本创建 1.格式要求:首行shebang机制 #!/bin/bash #!/usr/bin/python #!/usr/bin/perl 2.添 ...

  3. Appium 介绍及环境安装

    Appium是一个可用于测试iOS. Android操作系统和Windows桌面平台原生应用,移动网页应用和混合应用的自动化测试框架. 原生应用(Native App):用 android.iOS或者 ...

  4. Eplan P8 2.7 加密狗 感叹号 解决方法

    Eplan安装完加密狗后一直感叹号异常,最近也是查了很多办法,最后发现是少了个驱动的原因. 就是上面这个驱动,这里放上驱动链接:https://lanzous.com/id5gi8f ,或者随便找一个 ...

  5. 【SpringBoot1.x】SpringBoot1.x 安全

    SpringBoot1.x 安全 文章源码 环境搭建 SpringSecurity 是针对 Spring 项目的安全框架,也是 SpringBoot 底层安全模块默认的技术选型.他可以实现强大的 we ...

  6. HAProxy-1.8.20 根据后缀名转发到后端服务器

    global maxconn 100000 chroot /data/soft/haproxy stats socket /var/lib/haproxy/haproxy.sock mode 600 ...

  7. docker 删除和拉取镜像

    删除镜像 # docker rmi -f 镜像id # 删除指定镜像 docker rmi -f 25d5f6s564 # docker rmi -f 镜像id 镜像id # 删除多个镜像 docke ...

  8. kubernets之服务的实现方式

    一  服务如何通过kubernetes集群的组件来实现其功能 1.1  节点上的所有的服务相关的功能实现都是通过节点上面的kube-proxy来实现的,服务提供了一个或者多个服务IP以及端口对客户端开 ...

  9. 关于BAPI_GOODSMVT_CREATE中货物移动相关事务代码说明

    BAPI_GOODSMVT_CREATE参数 goodsmvt_code中的GM_CODE是为 BAPI 货物移动分配事务代码 其取值为下面对应的事务代码: 01 MB0102 MB3103 MB1A ...

  10. linux下安装nacos

    一.安装 1.下载安装包: https://github.com/alibaba/nacos/releases 2.解压 : tar -xzvf nacos-server-1.2.1.tar.gz 3 ...