洛谷P2602 [ZJOI2010]數字計數
阿新 • • 發佈:2021-08-05
洛谷P2602 [ZJOI2010]數字計數
數位dp
這也是一道比較基礎的數位dp題。
有一點需要注意,需要加上前導0的判斷,否則在統計0的個數時會多餘統計很多數
直接看程式碼吧(有註釋)
不會真的有人寫數位dp不用深搜吧,不會吧,不會吧
#include <iostream> #include <cstdio> #include <cstring> #define ll long long using namespace std; ll l, r, len; ll num[15], dp[13][13][2][2]; //dp[len][sum][flag][lim] ll dfs(ll len, ll now, ll sum, ll flag, ll lim){ //len:當前處理到x的第幾位,now:當前在查詢數字幾的個數,sum:當前數字出現了幾次,flag:前導0判斷(1:是 0:否),lim:上界判斷(1:有 0:無) if(!len) return sum; //處理完了,返回sum if(dp[len][sum][flag][lim] != -1) return dp[len][sum][flag][lim]; //記憶化 ll res = lim ? num[len] : 9; ll ans = 0; for(ll i = 0; i <= res; i++) ans += dfs(len - 1, now, sum + (!(flag && (!i)) && (i == now)), flag && (!i), lim && (i == res)); //這個sum傳遞好好看看,要判斷是否是前導0 return dp[len][sum][flag][lim] = ans; } ll solve(ll x, ll now){ len = 0; while(x){ num[++len] = x % 10; //這裡是倒著存x的每一位的 x /= 10; } memset(dp, -1, sizeof(dp)); //dp陣列還是-1 return dfs(len, now, 0, 1, 1); } signed main(){ scanf("%lld%lld", &l, &r); for(ll i = 0; i <= 9; i++) printf("%lld ",solve(r, i) - solve(l - 1, i)); //字首和思想統計答案 printf("\n"); return 0; }
完結撒花~