hdu_3555 bomb
数位动态规划
数位动态规划是求解一个大区间[L, R]中间满足条件Q的所有数字的个数(或者和,或其他)的一种方法。它通过分析每一位上的数字,一般用 dp[len][digit][...] 来表示状态“len位长的数字,最高位数字为digit所具有的xx特性”,利用记忆化搜索保存中间结果,从而加快求解速度。
通过求 f(n) 从0到n中满足条件Q的数字的个数,则所求的结果为 f(R) - f(L-1).
题目大意
给定数字n,找出从0到n中满足条件“数字k中有49(4和9连续)存在”的数字的个数。
题目分析
直接数位dp即可。
实现
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; typedef long long ll; ll dp[30][10]; //dp[len][digit]表示长度为len,且最高位为digit的满足条件Q的数字个数 ll base[30]; int bits[30]; ll Dfs(int len, int digit, bool end_flag, ll n){ if (len <= 1) return 0; if (!end_flag && dp[len][digit] != -1) return dp[len][digit]; ll ans = 0; int end = end_flag ? bits[len - 2] : 9; for (int i = 0; i <= end; i++){ if (digit == 4 && i == 9){ if (end_flag) ans += (1 + n % base[len - 2]); else ans += base[len - 2]; }else ans += Dfs(len - 1, i, end_flag && (i == end), n); } if (!end_flag) dp[len][digit] = ans; return ans; } int Init(ll n){ memset(bits, 0, sizeof(bits)); int k = 0; base[0] = 1; while (n){ bits[k++] = n % 10; base[k] = base[k - 1] * 10; n /= 10; } return k; } ll Solve(ll n){ int len = Init(n); return Dfs(len + 1, 0, true, n); } int main(){ int T; ll num; scanf("%d", &T); memset(dp, -1, sizeof(dp)); while (T--){ scanf("%I64d", &num); ll ret = Solve(num); printf("%I64d\n", ret); } return 0; }
在数据范围较大的时候,使用 long long int类型,但要注意所有使用long long int类型的变量被调用的函数中,参数形式均保持一致为long long int。