数位dp(二进制01问题)
Posted nonames
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数位dp(二进制01问题)相关的知识,希望对你有一定的参考价值。
题意:给你一个区间,求区间有多少个满足条件的数。条件是:把该数转为二进制后,如果0的数量大于等于1的数量,则为满足条件的数量。
题解:数位dp【pos】【sta】表示第pos位,pos前面位数的0数量-1数量为sta的,且满足条件的数的数量。
因为在dfs过程中sta可能为负数(数组下标不能为负数),但又并不能却定该数最终是否符合条件,所以sta初始值为32就避免了负数。因为前导零会影响结果,所以要分类讨论。
//#include <bits/stdc++.h> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <string> #include <stdio.h> #include <queue> #include <stack> #include <map> #include <set> #include <string.h> #include<time.h> #include <vector> #define ME(x , y) memset(x , y , sizeof(x)) #define SF(n) scanf("%d" , &n) #define rep(i , n) for(int i = 0 ; i < n ; i ++) #define INF 0x3f3f3f3f #define mod 20191117 #define PI acos(-1) using namespace std; typedef long long ll ; int a[40]; int dp[40][70]; int dfs(int pos , int sta , int lead , int limit) { if(pos == -1) return sta >= 32; if(!limit && !lead && dp[pos][sta] != -1) return dp[pos][sta]; int up = limit ? a[pos] : 1 ; int ans = 0 ; for(int i = 0 ; i <= up ; i++) { if(lead && i == 0) ans += dfs(pos-1 , sta , lead , limit && a[pos] == i); else ans += dfs(pos -1 , sta + (i == 0 ? 1 : -1) , false , limit && a[pos] == i); } if(!limit && !lead) dp[pos][sta] = ans ; return ans ; } int solve(int x) { int pos = 0 ; while(x) { a[pos++] = x % 2 ; x /= 2 ; } return dfs(pos-1 , 32 , true , true); } int main() { /*#ifdef ONLINE_JUDGE #else freopen("D:/c++/in.txt", "r", stdin); freopen("D:/c++/out.txt", "w", stdout); #endif*/ int l , r ; memset(dp , -1 , sizeof(dp)); scanf("%d%d" , &l , &r); printf("%d " , solve(r) - solve(l-1)); return 0; }
以上是关于数位dp(二进制01问题)的主要内容,如果未能解决你的问题,请参考以下文章