method one:
Step-by-step calculation for the case where each digit is a certain value
Difficulty: low
Practicality: low, only available when it is required to determine whether a digit appears in a digit
For example, find the case where there are no consecutive 62 and no 4 in the number
A number smaller than 456 can be considered like this,
4 5 6
4 5 (0~6)
4 (0~4) (0~9)
(0~3) (0~9) (0~9)
First calculate how many numbers can satisfy ( 0~399) when the hundreds place is 0, 1, 2, and 3
Then calculate how many numbers can satisfy ( 000~049) when the tens place is 0, 1, 2, 3, and 4
Finally , how many numbers can be satisfied when the tens place is 0~6 ( 000~006)
Here it is explained that 0~49 is equivalent to 400~449
If these numbers are preceded by 4 or 62, these numbers do not count
does not appear, the value of the preceding number has no effect
Explain the actual operation
dp[][], the first dimension represents the number of digits (one, ten, hundred, etc.), and the second dimension represents the number of digits on the digit
First assign the initial value, obviously the value of each one except 4 is 1
Then the state transition equation is
dp[i][j]=dp[i-1][0]+ dp[i-1][1]+…+dp[i-1][9]
Then add the judgment of 62 and 4
FOR(i,2,6)
{
FOR(j,0,9)
{
if(j==4) continue;
FOR(k,0,9)
{
if(k==4||(j==6&&k==2)) continue;
dp[i][j]+=dp[i-1][k];
}
}
}
Among them , the number of digits of j is to the left of k, which is used to judge whether 62 exists or not.
Initialization is relatively simple, but there are many error-prone points in the solution process
First, put out each digit of the read number.
while(k)
{
a[++cnt]=k%10;
k/=10;
}
a[cnt+1]=0;
It is necessary to ensure that the previous bit of the largest bit of the array is 0, because this bit will be used in subsequent judgments
First from high to low
For example , 456, we first calculated 0~399, because there are 4, the following numbers are illegal
So the high-order number determines whether the low-order number is valid
So the loop ends when these numbers appear
If the hundreds place is 3, we want to calculate 0~299, so we actually calculate
0~99
100~199
200~299
That is, a number smaller than 3, so the range of the loop is 0~( a[i]-1)
This calculation method will calculate one less number when calculating the last digit.
For example , 123, we actually calculated 0~122, so the number to be calculated should be incremented by 1
ROF(i,cnt,1)
{
FOR(j,0,a[i]-1)
{
if((a[i+1]==4&&j==9)) continue;
ans+=dp[i][j];
}
if((a[i+1]==4&&a[i]==9)) break;
}
The above methods are very basic, error-prone to write and very limited in use
Method Two:
memoized search dp
Difficulty: high
Usability: high, almost all situations
Here first add the cognition of dp
Take the tower as an example
If you enumerate all the states, there will be a lot of very similar states with only a small difference between them, and you will be doing a lot of repetitive operations, and if you find a pattern that takes all the states that have been computed, and applies In the operations to be performed, the efficiency will be greatly improved.
However, the case of number towers is very monotonic, and when you reason about the state, the state is fully represented by just a one-dimensional array. But even so, we can still do memoized searches.
Memorized search means - after judging the state, the next time you encounter it, you can directly borrow the past results.
Code:
int dfs(int x,int y)
{
if(dp[x][y])
return dp[x][y];
if(x>n||y>n) return 0;
dp[x][y]=max(dfs(x+1,y),dfs(x+1,y+1))+a[x][y];
return dp[x][y];
}
Then dp[1][1] is the answer we need, and its operation order is consistent with the conventional state equation writing.
Therefore, we can find that dp and memoization search are closely related. If you can't understand digital dp search at present, it is better to use memoization search to rewrite previous dp questions to deepen your understanding.
An example of digital dp for memoized search is given below
ll dfs(int pos,int sta,int limit)
// The four parameters from 3 to 4 are the current bit, the state (may use two numbers to represent the state), and the upper limit
{
//cout<<pos<<" "<<sta<<" "<<f[sta]<<endl;
if(pos==0)//Go to the last digit to determine whether the number satisfies the condition
{
return f[sta]==1;
}
if(!limit&&dp[pos][sta]!=-1)
//When the number of digits is the same and the state is the same, the past result is directly borrowed, and the limit is whether the upper limit is reached. For example, the last calculation was 1000 to 1999, which is exactly the same as the current 2000 to 2999, but the upper limit (initial input) is less than 2999, so cannot borrow
{
return dp[pos][sta];
}
int up=limit?a[pos]:9,s,g=sta,k=sta;
ll ans=0;
FOR(i,0,up)
{
if(i==0)
{
if(sta!=0)
{
s=g%3;
g/=3;
if(s==0||s==1) k=sta+t[i];
else k=sta-t[i];
}
}
else
{
s=g%3;
g/=3;
if(s==0||s==1) k=sta+t[i];
else k=sta-t[i];
}
ans+=dfs(pos-1,k,limit&&i==up);
}
if(!limit)//When the upper limit is not reached, record the status
dp[pos][sta]=ans;
return ans;
}
ll solve(ll x)
{
int pos=0;
while(x)
{
a[++pos]=x%10;
x/=10;
}
a[pos+1]=0;
return dfs(pos,0,1);
}
The corresponding questions correspond to SPOJ BALNUM , and the actual questions are rewritten according to the needs, and there is no generality.
By the way, let’s talk about this question first. The question requires how many BALNUM are in l and r. BALNUM means that the odd number in the digits appears even number of times, the even number appears odd number of times, and the ones that do not appear are not considered, such as 1, 111, 11111, 22 , 2222 are BALNUM.
Use ternary to represent the status of 0 to 9, 0 is not present, 1 is odd number of times, 2 is even number of times.
Since only 1 and 2 are added to the calculation, all eligible state numbers can be processed by the following binary
Note: t[j] is 3 to the j power
FOR(i,1,pow(2,10)-1)
{
int l = i, ret = 0;
FOR(j,0,9)
{
if(l&1) ret+=((j%2)==1?2*t[j]:t[j]);
l>>=1;
}
//cout<<i<<" "<<ret<<endl;
f [ret] = 1;
}