【hdu2089】不要62

惊奇地发现今天居然和dalao的题单重了不少23333333333333

这是我第一次做数位dp,感觉这个题目还是比较兹磁的

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int l,r,dp[20][15],a[20];
int dfs(int pos,int las,int fl,bool flag)//pos是当前位置,las是上次选的那个数,fl判断上次选的数是否为6,flag判断pos位上是否有枚举限制 
{
    if(pos==0)//答案成立,返回1 
        return 1;
    if(!flag&&dp[pos][las]!=-1)//如果flag==1的时候也返回,那么像213的时候会使答案偏大 
        return dp[pos][las];
    int ding=(flag)?a[pos]:9;//判断这一位上是否有限制最大能枚举的数 
    int re=0;
    for(int i=0;i<=ding;i++)
    {
        if(i==4||(las==6&&i==2))//不能出现4或者62 
            continue;
        re+=dfs(pos-1,i,i==6,flag&&i==a[pos]);
    }
    if(!flag)//如果flag==1说明这一位有限制,并不完全将第pos位上一次选的las的状态完全包含,所以不能赋值 
        dp[pos][las]=re;
    return re;
}
int solve(int x)
{
    int pos=0;
    while(x>0)//先拆分成一位位的数字 
        a[++pos]=x%10,x/=10;
    return dfs(pos,-1,0,1);//flag初始设为0是因为数位长度+1位确实是0 
}
int main()
{
    memset(dp,-1,sizeof(dp));//每次输入的只是不同的数据范围,但是不会影响dp数组的答案,所以只初始化一遍就好 
    while(~scanf("%d%d",&l,&r))
    {
        if(l==0&&r==0)
            break;
        printf("%d\n",solve(r)-solve(l-1));//l也被包含在答案区间一部分 
    }
}

 

posted @ 2017-10-25 21:45  那一抹落日的橙  阅读(157)  评论(1编辑  收藏  举报