HDU - 4734 F(x) - 數位dp
阿新 • • 發佈:2020-12-09
求出在\([1, b]\)裡有多少個數字的\(F(i) \leq F(a)\)
首先算出\(F(a)\)的值,然後套一下數位dp板子即可
同時記錄其權值變化,對於每一個base就是\(2^{pos}\)
但是選擇記錄當前權值然後最後比較是否小於等於\(F(a)\)是不行的
因為記憶化搜尋就會記錄有多少個權值是小於第一個\(F(a)\),所以需要改變一下。
設初始值為\(F(a)\),然後去減每位的權值,最後判斷權值是否大於等於0即可。
記住,記憶化搜尋的話,就必須保持記錄的值是同一條件的
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int dp[10][4600]; int a[20]; int base[30]; int maxx = 0; int dfs(int pos, bool limit, int now){ if(pos == -1) return now >= 0; if(now < 0) return 0; if(!limit && now >= 0 && dp[pos][now] != -1) return dp[pos][now]; int up = limit ? a[pos] : 9; int tmp = 0; for(int i = 0; i <= up; i++) { tmp += dfs(pos - 1, limit && i == up, now - i * base[pos]); } if(!limit && now >= 0) dp[pos][now] = tmp; return tmp; } int solve(int n){ int pos = 0; while(n){ a[pos++] = n % 10; n /= 10; } return dfs(pos - 1, 1, maxx); } void init(int n){ int base = 1; while(n){ maxx += n % 10 * base; n /= 10; base *= 2; } } int main(){ for(int i = 0; i <= 30; i++) base[i] = 1 << i; int t; memset(dp, -1, sizeof(dp)); scanf("%d", &t); for(int i = 1; i <= t; i++) { maxx = 0; int a, b; scanf("%d%d", &a, &b); init(a); printf("Case #%d: %d\n", i, solve(b)); } return 0; }