标签:++ ref 传送门 基础 答案 ace mit limit href
传送门: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 }
标签:++ ref 传送门 基础 答案 ace mit limit href
原文地址:https://www.cnblogs.com/YangKun-/p/12633636.html