The problem was done with a digital DP before, but it didn't get a thorough understanding. Today, I think about it a little bit better than before.
Test instructions
is to ask you to find the number of numbers that do not contain 4 and 62 within the range of [n,m].
Ideas:
1) Violence
2) Digital DP:
Before doing a digital DP, we first need to initialize, and we define F[I][J] to have several of the normal numbers in the I-digits starting with J.
We can then initialize the F array with a three-layer for loop.
void Init () {F[0][0]=1;<span style= "White-space:pre" ></span>//Don't forget for (int i=1;i<=7;i++) {for (int j=0; j<=9;j++) {for (int k=0;k<=9;k++) {if ((j!=4) && (!) ( j==6&&k==2)) {<span style= "White-space:pre" ></span>//here's the logical relationship first I wrote | | (j!=6&&k!=2), this is problematic f[i][j]=f[i-1][k]+f[i][j];}}}}
The first layer of our for is the number, the second layer we will be able to take the first bit to enumerate the numbers, and the third layer we enumerate the numbers that the I-1 bit can fetch. Since the current value of the I-bit relationship is only related to the i-1 bit and the current I-bit, we can get this recursive type.
The most important thing is to figure out a few.
Today I finally figured out why Cal (m+1)-cal (n), and sometimes Cal (M)-cal (n-1).
This depends on how your own DP is defined. When you define how many of the first I number are eligible, then I write the first one.
If the number of the first I is defined to include the number of itself is eligible, then I write the second way.
But the two formulations are essentially no different.
This question I write is the first, that is, does not contain itself.
The method of seeking is:
We mark from low to High to 1~n (n is the number of digits), and then from the high start to look for, and then replace the number must not be greater than the current value, and because I define not to include itself, so it is less than the current value of the bit, and then ans+= has been obtained f[i][j], So one bit pushed down until the last one, so that's why we added 1 to the last one.
Of course, when this is 4, or this is 2 and the previous one is 6, then just jump out of the loop.
int cal (int x) {int tmp=x,t=0;while (TMP) {DIG[++T]=TMP%10;TMP=TMP/10;} Dig[t+1]=0;int ans=0;for (int i=t;i>=1;i--) {for (int j=0;j<dig[i];j++) {if (j!=4) && (!) ( j==2&&dig[i+1]==6))) ans+=f[i][j];} if ((dig[i]==4) | | | (dig[i]==2&&dig[i+1]==6)) break;} return ans;}
At first I couldn't figure out why J Loop to less than dig[i] is good, is actually the definition of the problem.
#include <stdio.h> #include <string.h> #include <queue> #include <map> #include <set># include<queue> #include <stack> #include <math.h> #include <iostream> #include <algorithm >using namespace std; #define MAXN 11int dig[maxn];int f[maxn][maxn];void init () {f[0][0]=1;for (int i=1;i<=7;i++) { for (int j=0;j<=9;j++) {for (int k=0;k<=9;k++) {if ((j!=4) && (!) ( j==6&&k==2))) {f[i][j]=f[i-1][k]+f[i][j];}}}} int cal (int x) {int tmp=x,t=0;while (TMP) {DIG[++T]=TMP%10;TMP=TMP/10;} Dig[t+1]=0;int ans=0;for (int i=t;i>=1;i--) {for (int j=0;j<dig[i];j++) {if (j!=4) && (!) ( j==2&&dig[i+1]==6))) ans+=f[i][j];} if ((dig[i]==4) | | | (dig[i]==2&&dig[i+1]==6)) break;} return ans;} int main () {int n,m;init (), while (~SCANF ("%d%d", &n,&m)) {if (n==0&&m==0) break;printf ("%d\n", Cal (M+1) -cal (n)); <span style= "White-space:pre" ></span>//!!!}}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
HDU (2089)--Not 62 (digital DP)