POJ-3252——Round Numbers

POJ-3252——Round Numbers

传送门:http://poj.org/problem?id=3252

题意:求n-m中二进制表示0的数量不小于1的数的个数

要找二进制0和1的个数,因为是按位数来找的,可以考虑数位dp

状态dp[pos][_0][_1] 表示为dp[当前第几位][含0的个数][含1的个数]

这个题注意dfs传参的时候要多传进去一个lead(是否是前导0)因为此时前导0的存在会影响最终的答案

之前的数位dp都是在十进制的基础上dp,而本题是二进制,拆分的时候拆成二进制就好了,而且枚举的最高位也从9变成了1

上代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 using namespace std;
 4 #define ll long long
 5 ll a[109];
 6 ll dp[50][50][50];
 7 ll dfs(ll pos,ll _0,ll _1,ll lead,bool limit)
 8 {
 9     if(pos<=0) return _0>=_1;
10     if(!limit&&dp[pos][_0][_1]!=-1) return dp[pos][_0][_1];
11     ll up=limit?a[pos]:1;
12     ll res=0;
13     for(ll i=0; i<=up; i++)
14     {
15         res+=dfs(pos-1,!lead&&i==0?_0+1:_0,i==1?_1+1:_1,lead&&(i==0),limit&&i==a[pos]);
16     }
17     if(!limit) dp[pos][_0][_1]=res;
18     return res;
19 }
20 ll solve(ll x)
21 {
22     ll pos=0;
23     while(x)
24     {
25         a[++pos]=x%2;
26         x/=2;
27     }
28     return dfs(pos,0,0,1,1);
29 }
30 int main()
31 {
32     memset(dp,-1,sizeof(dp));
33     ll a,b;
34     scanf("%lld%lld",&a,&b);
35     printf("%lld\n",solve(b)-solve(a-1));
36     return 0;
37 }

 

posted @ 2020-04-04 19:25  L·S·D  阅读(151)  评论(0编辑  收藏  举报