zoukankan      html  css  js  c++  java
  • 【poj3252】 Round Numbers (数位DP+记忆化DFS)

    题目大意:给你一个区间$[l,r]$,求在该区间内有多少整数在二进制下$0$的数量$≥1$的数量。数据范围$1≤l,r≤2*10^{9}$。

    第一次用记忆化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,op^1,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
    ",get(b)-get(a-1));    
    41     }
    42     
    43 }
  • 相关阅读:
    Java编程之路相关书籍
    JAVA中的Random()函数
    在鼠标右键上加入使用notepad++编辑
    更改IE浏览器的收藏夹位置
    Java四类八种数据类型
    成为Java顶尖程序员 ,看这11本书就够了
    面向对象(多异常的声明与处理)
    面向对象(异常try-catch)
    面向对象(异常概述)
    面向对象(局部内部类和匿名内部类)
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/7743064.html
Copyright © 2011-2022 走看看