【poj3252】 Round Numbers (数位DP+记忆化DFS)
题目大意:给你一个区间[l,r],求在该区间内有多少整数在二进制下0的数量≥1的数量。数据范围1≤l,r≤2∗109。
第一次用记忆化dfs写数位dp,感觉神清气爽~(原谅我这个蒟蒻,原先写的四不像数位dp至少需2h,用真记忆化dfs不到半小时写出)
我们用f[i][j]表示在最后的i+j为中,用了i个0,j个1的方案数(第i+j位也可以是0)。该方程转移显然为f[i][j]=f[i−1][j]+f[i][j−1]。
于是我们用记忆化dfs去求答案,dfs(n,op,x,y)表示你构造到从后往前数第n位,是否有压着上限,0的数量,1的数量。
若无压着上限,则答案显然为dfs(n−1,op,x,y−1)+dfs(n−1,op,x−1,y)。
若压着上限且第num[n]位为0,则答案为dfs(n−1,op,x−1,y)。 否则答案为dfs(n−1,op,x,y−1)+dfs(n−1,op1,x−1,y)。
搜索时用记忆化加速即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define L int 5 #define M 50 6 using namespace std; 7 L f[M][M]={0};//前i+j位中,用了i个0,j个1的方案数 8 int num[M]={0},cnt=0; 9 L dfs(int n,bool op,int x,int y){//当前处理到第n位,且第cnt位到第n+1为已经确定,第n-1位是否压着上限,计划用x个0,和y个1。 10 if(x==-1||y==-1) return 0; 11 if(!op&&f[x][y]!=-1) return f[x][y]; 12 if(!op){ 13 f[x][y]=dfs(n-1,op,x-1,y)+dfs(n-1,op,x,y-1); 14 return f[x][y]; 15 } 16 if(!num[n]) return dfs(n-1,op,x-1,y); 17 return dfs(n-1,0,x-1,y)+dfs(n-1,op,x,y-1); 18 } 19 L get(L x){ 20 if(x==0) return 0; 21 memset(num,0,sizeof(num)); cnt=0; 22 int b[2]={0}; 23 while(x){ 24 num[++cnt]=x&1; 25 b[x&1]++; x>>=1; 26 } 27 L sum=0; 28 if(b[0]>=b[1]) sum++; 29 for(int i=1;i<=cnt;i++){ 30 for(int j=1;j*2<=i;j++) 31 sum+=dfs(i-1,i==cnt,i-j,j-1); 32 } 33 return sum; 34 } 35 int main(){ 36 L a,b; 37 while(cin>>a>>b){ 38 memset(f,-1,sizeof(f)); 39 for(int i=0;i<M;i++) f[0][i]=f[i][0]=1; 40 printf("%d\n",get(b)-get(a-1)); 41 } 42 43 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!