數位DP入門 HDU 2089 不要62 註釋詳解
阿新 • • 發佈:2018-12-18
題意:輸出一個區間【m,n】內所有不含“62"and"4" 的數字個數;n<=10^7;
數位dp一般應用於:
求出在給定區間[A,B]內,符合條件P(i)的數i的個數.
條件P(i)一般與數的大小無關,而與 數的組成 有關.
具體的理論過程我就不解釋了,我看了好多的文章,最後還是直接看程式碼註釋看懂的;
所以 還是直接上程式碼:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int dp[10][10];//dp[i][j]表示第i位是數j時符合條件的數字數量 int d[10];//digit[i]表示n從右到左第i位是多少 void init() { dp[0][0] = 1; for (int i = 1; i <= 7; ++i)//列舉第i位 for (int j = 0; j <= 9; ++j)//表示第i位是數j時符合條件的數字數量 for (int k = 0; k <= 9; ++k)//列舉第i-1位的情況 if (j != 4 && !(j == 6 && k == 2))///如果符合條件 !62 && !4 dp[i][j] += dp[i - 1][k]; } int solve(int n) { int ans = 0; int len = 0; while (n) ///計算n的digit陣列 { d[++len] = n % 10; n /= 10; } d[len + 1] = 0;//最高位 置零 //計算[0,n]區間滿足條件的數字個數 for (int i = len; i >= 1; --i)///注意:從最高位開始列舉 { for (int j = 0; j < d[i]; ++j) //列舉第i位的取值j { if (d[i + 1] != 6 || j != 2)//第i位取j滿足條件 ans += dp[i][j]; }//第i位該狀態已經不滿足條件,則i位以後都不可能滿足條件,結束迴圈 //例如 62...or 4... if (d[i] == 4 || (d[i + 1] == 6 && d[i] == 2)) break; } return ans; } int main() { int m, n; init(); while (scanf("%d%d", &m, &n) == 2) { if (n == 0 && m == 0) break; printf("%d\n", solve(n + 1) - solve(m));///用[0,m]-[0,n)即可得到區間[n,m] } return 0; }