博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[HDU 4734]F(x)[数位DP]
阅读量:5257 次
发布时间:2019-06-14

本文共 1357 字,大约阅读时间需要 4 分钟。

题意:

将一个十进制数

n = dn dn-1 ... d0

视为二进制. 即

F(n) = dn*2^n + ... + d0*2^0.

给出A, B. 求0 ... B之间, 该值不大于F(A)的数的个数.

思路:

数位DP.

数位DP的优点在于, 你不需要直到这个答案是怎么来的, 只需要知道递推式. 这个答案的生成过程就在递推的过程中.

dp [ i ] [ j ] 表示 i 位的数{ x } 中 F ( x ) 小于 j 的数的个数.

 

#include
#include
#define maxn 16int dp[maxn][111111];int d[maxn];int n;long long tt;long long dfs(int len ,int pre ,bool fp){ if(pre<0)return 0;//说明上一层枚举的数超过了上限,没有可用的情况 if(!len)return 1;//说明上一层是个位.那么只需要把各个数累加起来就可以 if(!fp&&dp[len][pre]!=-1)return dp[len][pre];//记忆化搜索 int fpmax=fp?d[len]:9;//取该位取值的最大值 int ret=0; for(int i=0;i<=fpmax;i++){//从最大长度向下,每一个长度的所有取值都要遍历到, //一旦该位的取值不是紧贴最大值,fp就false. ret+= dfs(len-1,pre-i*(1<<(len-1)),fp&&i==fpmax); } if(!fp)dp[len][pre]=ret;//记录结果 return ret;}long long calc(long long a){ int len=0; memset(d,0,sizeof(d)); while(a){ d[++len]=a%10; a/=10; } return dfs(len,tt,true);}int get(int x){ int tmp=1; int ans=0; while(x){ ans+=(x%10)*tmp; x/=10; tmp<<=1; } return ans;}int main(){ long long a,b; int nc; scanf("%d",&nc); int d=1; memset(dp,-1,sizeof(dp)); while(nc--){ scanf("%I64d%I64d",&a,&b); tt=get(a); printf("Case #%d: %I64d\n",d++,calc(b)); } return 0;}

 

 

转载于:https://www.cnblogs.com/suncoolcat/p/3322829.html

你可能感兴趣的文章
项目管理之路(1):初步踏入项目管理
查看>>
Java 中 静态方法与非静态方法的区别
查看>>
crypto加密
查看>>
Apache Jackrabbit 2.6.0 发布
查看>>
echarts饼图显示百分比
查看>>
第十二次作业
查看>>
喜欢的话
查看>>
JMS消息
查看>>
16位整数,32位整数,64位整数
查看>>
Jenkins+ProGet+Windows Batch搭建全自动的内部包(NuGet)打包和推送及管理平台
查看>>
Jenkins里邮件插件触发器配置和Send to Developers到底是什么意思(转)
查看>>
angular/cli安装
查看>>
网页记账本开发三
查看>>
11gR1 Patchset 2 ~ 11.1.1.3.0 (SOA) features ..
查看>>
Hdu 1708 Fibonacci String
查看>>
java lock锁住特定对象
查看>>
JAX-WS 访问SSL 的WebService 老是HTTP transport error: Connection refused错误的解决办法。...
查看>>
面向对象与函数式的对比
查看>>
php上传文件及头像预览
查看>>
程序猿加班的不归路!
查看>>