首页 > 代码库 > poj 3252 Round Numbers

poj 3252 Round Numbers

题目链接:http://poj.org/problem?id=3252

题意:给出一个二进制区间,求出0的个数不小于1的个数这样的二进制个数

解法:数位DP,定义状态dp[len][num_zero][num_one],num_zero 定义为写0的个数。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define inf 0x7fffffff
 8 #define exp 1e-10
 9 #define PI 3.141592654
10 using namespace std;
11 typedef long long LL;
12 LL digit[35];
13 LL dp[35][35][35];
14 LL dfs(LL len,LL num_zero,LL num_one,bool fp,int flag)
15 {
16     if (!len)
17     {
18         if (flag && num_zero>=num_one) return 1;
19         return 0;
20     }
21     if (!fp && dp[len][num_zero][num_one]!=-1)
22     return dp[len][num_zero][num_one];
23     LL ret=0;
24     LL fpmax= fp ? digit[len] : 1;
25     for (LL i=0 ;i<=fpmax ;i++)
26     {
27         LL s= i==1 ? 1 : 0;
28         LL s2= flag && i==0 ? 1 : 0;
29         ret += dfs(len-1,num_zero+s2,num_one+s,fp && i==fpmax,flag || i==1);
30     }
31     if (!fp) return dp[len][num_zero][num_one]=ret;
32     return ret;
33 }
34 LL f(LL n)
35 {
36     LL len=0;
37     while (n)
38     {
39         digit[++len]=n%2;
40         n /= 2;
41     }
42     return dfs(len,0,0,true,0);
43 }
44 int main()
45 {
46     LL a,b;
47     while (cin>>a>>b)
48     {
49         memset(dp,-1,sizeof(dp));
50         printf("%I64d\n",f(b)-f(a-1));
51     }
52     return 0;
53 }