Luo Gu P2657 (digital DP)

### Los Valley P2657 topic Link ###

 

Title effect: to give you a range of number [A, B], you ask within this range, there are several numbers satisfying the following conditions:

1, the difference between the number of digits in the two adjacent least 2.

2, do not include leading zeros.

 

Very simple digital DP, may want to simply mark a leading zero lead, before a number of pre, statistical answers to violence, then the memory of the line, but some places still a little careful.

For example, in the enumeration to the first significant digit (ie, non-leading zero), it is currently only a number, but we need to set q = true (q said in the enumeration to the current position, whether the condition that the adjacent bits difference is reached 2). That is when I need to ensure that the enumeration to the second significant digit to the difference compared with the first significant digit for, then when enumerating the first significant bit, can not make q == false.

Then according to the sample 1 can know, single digits are also considered. So in order to make the first meet abs (i - pre)> = 2, then, then we need to make a start can be pre == -1, because i will be at least one.

 

code show as below:

According to enumerate the conditions digit

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
int A,B;
int a[12],dp[12][12];
ll dfs(int pos,int pre,bool lead,bool limit){
    if(pos==0) return 1;
    if(!limit&&!lead&&dp[pos][pre]!=-1) return dp[pos][pre];
    int up=limit?a[pos]:9;
    ll res=0;
    for(int i=0;i<=up;i++){
        if(lead&&i==0) res+=dfs(pos-1,-1,true,limit&&i==a[pos]);
        else{
            if(abs(i-pre)>=2){
                res+=dfs(pos-1,i,false,limit&&i==a[pos]);
            }
        }
    }
    if(!limit&&!lead) dp[pos][pre]=res;
    return res;
}
ll solve(ll x)
{
    int pos=0;
    while(x){
        a[++pos]=x%10;
        x/=10;
    }
    return dfs(pos,-1,true,true);
}
int main()
{
    //freopen("test.in","r",stdin);
//    freopen("test.out","w",stdout);
    memset(dp,-1,sizeof(dp));
    while(~scanf("%d%d",&A,&B)){
    printf("%lld\n",solve(B)-solve(A-1));
}
}

 

Enumerated directly according to the value of q is determined whether correct. D DP need to save the state q.

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
int A,B;
int a[12],dp[12][12][2];
ll dfs(int pos,int pre,bool q,bool lead,bool limit){
    if(pos==0) return q;
    if(!limit&&!lead&&dp[pos][pre][q]!=-1) return dp[pos][pre][q];
    int up=limit?a[pos]:9;
    ll res=0;
    for(int i=0;i<=up;i++){
        if(lead&&i==0) res+=dfs(pos-1,pre,q,true,limit&&i==a[pos]);
        else res+=dfs(pos-1,i,q&&(abs(pre-i)>=2),false,limit&&i==a[pos]);
    }
    if(!limit&&!lead) dp[pos][pre][q]=res;
    return res;
}
ll solve(ll x)
{
    int pos=0;
    while(x){
        a[++pos]=x%10;
        x/=10;
    }
    return dfs(pos,-1,true,true,true);
}
int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    memset(dp,-1,sizeof(dp));
    scanf("%d%d",&A,&B);
    printf("%lld\n",solve(B)-solve(A-1));
}

 

Guess you like

Origin www.cnblogs.com/Absofuckinglutely/p/11441584.html