poj 3252 Round Numbers 數位dp
阿新 • • 發佈:2017-05-11
變量 數量 div read sdn .net blog air ble
題目鏈接:
http://poj.org/problem?id=3252
題意:
求一段區間中二進制中0的數量要不能少於1的數量的數的個數。
思路:
套路 都是套路
http://blog.csdn.net/wust_zzwh/article/details/52100392
dp[pos][num],到當前數位pos,0的數量減去1的數量為num的方案數,一個簡單的問題,中間某個pos位上num可能為負數(這不一定是非法的,因為我還沒枚舉完嘛,只要最終的num>=0才能判合法,中途某個pos就不一定了),這裏比較好處理,Hash嘛,最小就-32吧(好像),直接加上32,把32當0用。
顯然我要統計0的數量,前導零是有影響的。dfs記憶化的時候要加一個變量lead代表這位是不是當前數的前導0
代碼:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 typedef long long ll; 6 #define MS(a) memset(a,0,sizeof(a)) 7 #define MP make_pair 8 #define PB push_back 9 const int INF = 0x3f3f3f3f; 10 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 11 inline ll read(){12 ll x=0,f=1;char ch=getchar(); 13 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 14 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 15 return x*f; 16 } 17 ////////////////////////////////////////////////////////////////////////// 18 const int maxn = 1e5+10; 19 20 int l,r,dp[50][maxn],a[50]; 21 22 int dfs(int pos,int sta,int lead,intlimit){ 23 if(pos == -1) return sta>=32; 24 if(!lead && !limit && dp[pos][sta]!=-1) return dp[pos][sta]; 25 26 int up = limit ? a[pos] : 1; 27 int re = 0; 28 for(int i=0; i<=up; i++){ 29 if(lead && i==0) re += dfs(pos-1,sta,lead,limit&&i==a[pos]); 30 else re += dfs(pos-1,sta+((i==0)?1:-1),lead&&i==0,limit&&i==a[pos]); 31 } 32 if(!lead && !limit) dp[pos][sta] = re; 33 return re; 34 } 35 36 int solve(int x){ 37 int pos = 0; 38 while(x){ 39 a[pos++] = x%2; 40 x /= 2; 41 } 42 int re = dfs(pos-1,32,true,true); 43 return re; 44 } 45 46 int main(){ 47 memset(dp,-1,sizeof(dp)); 48 cin >> l >> r; 49 int ans = solve(r) - solve(l-1); 50 51 cout << ans << endl; 52 53 return 0; 54 }
poj 3252 Round Numbers 數位dp