POJ 3252 Round Numbers(数位dp)
发布日期:2021-05-07 06:22:53 浏览次数:24 分类:精选文章

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

数位dp

数位dp归为计数dp,通常需要统计一个区间[L,R]内满足某些限制条件的个数
附上找到的一位大佬的博客,日常转载不看https://blog.csdn.net/wust_zzwh/article/details/52100392

POJ 3252 Round Numbers

题目大意
给定区间,求出区间内的数转化成二进制后0的个数大于等于1的个数的数的个数。

由于一个二进制数的最高位一定为1,所以需要用first标记最高位是否是1。如果是的话,那么这一位随便放。

就这个题解看着还舒服点,但是看了两个小时还是懵懵懂懂…自闭

#include 
#include
#include
#include
using namespace std;int dp[50][50][50], bit[50];//dp[len][num0][num1]//flag表示最高位是否有限制,1表示有限制 //first表示第一个1是否放下,1表示没放下 int dfs(int highBit, int num0, int num1, int flag, int first){ if (highBit==0) return num0>=num1; if (flag==0 && first==0 && dp[highBit][num0][num1]!=-1) return dp[highBit][num0][num1]; int ans=0; int end=flag?bit[highBit]:1; for (int digit=0; digit<=end; digit++){ if (first){ if (digit==0) ans+=dfs(highBit-1, 0, 0, flag&&digit==end, 1); else ans+=dfs(highBit-1, num0, num1+1, flag&&digit==end, 0); }else{ if (digit==0) ans+=dfs(highBit-1, num0+1, num1, flag&&digit==end, 0); else ans+=dfs(highBit-1, num0, num1+1, flag&&digit==end, 0); } } if (flag==0 && first==0) dp[highBit][num0][num1]=ans; //记忆化 return ans;}int solve(int n){ //求出从0到n所有满足条件的数的个数 int len=0; while (n){ bit[++len]=n&1; //转成二进制 n>>=1; } int ans=dfs(len, 0, 0, 1, 1); //最开始最高位有限制,1没放下 return ans;}int main(){ memset(dp, -1, sizeof(dp)); int l, r; while (scanf("%d%d", &l, &r)!=EOF){ printf("%d\n", solve(r)-solve(l-1)); } return 0;}
上一篇:i春秋 web_1-5
下一篇:POJ 1185 炮兵阵地(状压dp)

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2025年03月27日 14时21分59秒