数位dp基础(类似模板) HDU 2089+3555

来源:互联网 发布:博泰与创业软件 编辑:程序博客网 时间:2024/05/22 03:36

2089:求区间内不含62 和4的数字的个数

简单的数位dp,数位dp也就是搜索,按照位数来搜的,所以时间上应该是很快的,对于搜索,确定好当前所在长度(也就是搜到的当前数的长度),约束条件,还有是不是最后一个这个条件,

代码+解释

/* I believe xiaoxuzizhucan*/#include<stdio.h>#include<string.h>#include<stdlib.h>#include<algorithm>using namespace std;#include<math.h>#include <queue>long long a[100];long long dp[200][5];//dfs(当前所在的位数,上一个数的i是不是等于6,是不是最后一位)long long dfs(long long pos,long long have,long long flag){    if(pos==0)//如果长度为0,也就是所搜到最后了,所以返回1,也就是这个数不含4和62,一位如果含有4和62,那就不会搜索到这一步,在下面的搜素过程中就continue了    {        return 1;    }    if(flag==0&&dp[pos][have]!=-1)//同理,剪枝头,我不是很懂。。其实删去应该也是对的吧,    {        return dp[pos][have];    }    long long sum=0;    long long end=flag?a[pos]:9;//求该为所能搜索的最大值    for(long long i=0; i<=end; i++)    {        if(i==4||have&&i==2)//如果当前为为4,或者上一个状态为6并且这一个状态为2,也就是出现4或者出现62,那么就不要你继续往下搜索了。            continue;        sum+=dfs(pos-1,i==6,flag&&i==end);//如果当前没有出现过4和62,然后就判断当前位是不是等于6,    }    if(flag==0)//入股不是最后一位,那么久赋值,方便上面剪枝使用        dp[pos][have]=sum;    return sum;}long long solve(long long n){    long long len=1;    while(n)    {        a[len++]=n%10;        n/=10;    }    //printf("%d\n",len);    return dfs(len-1,0,1);}int main(){    long long n,m;    memset(dp,-1,sizeof(dp));    while(scanf("%I64d%I64d",&n,&m)!=EOF)    {        if(n==0&&m==0)            break;        printf("%I64d\n",solve(m)-solve(n-1));    }}

3555:

题意,让你找小于n的数中含有49的个数有多少。

同样也是很裸的数位dp,就不断地搜索就好了呗,想好状态变化就好了。

代码+解释

/* I believe xiaoxuzizhucan*/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<algorithm>using namespace std;#include<math.h>long long a[150];long long dp[150][5];//dfs(当前数的长度,上一位是不是6,是不是最后一位)long long dfs(long long pos,long long have ,long long flag){    if(pos==0)//长度为0如果have==2,也就是出现过49就返回1,表述出现了一个    {        if(have==2)            return 1;        else return 0;    }    if(flag==0&&dp[pos][have]!=-1)//剪枝,也就是说如果当前位不是最后一位,并且被访问过,就直接返回        return dp[pos][have];    long long end=flag?a[pos]:9;//确定当前为最大值,    long long sum=0;    for(long long i=0; i<=end; i++)    {        long long temphave=have;        if(have==1&&i!=4)//如果上一个是1,这一个不是1,那么就不可能有49            temphave=0;        if(have==0&&i==4)//如果上一个不可能是49,但是这一个是4,那么标记为1,也就是表示上一个状态为4            temphave=1;        if(have==1&&i==9)//如果上一个状态为4(have=1)并且这个状态为9,那么就出现49了,所以have==2代表49出现过            temphave=2;        sum+=dfs(pos-1,temphave,flag&&i==end);    }    if(flag==0)//若果不是在最后一位        dp[pos][have]=sum;    return sum;}long long suan(long long x){    long long len=1;    while(x)    {        a[len++]=x%10;        x/=10;    }    return dfs(len-1,0,1);    }int  main(){    long long test;    memset(dp,-1,sizeof(dp));    scanf("%I64d",&test);    while(test--)    {        long long n;        scanf("%I64d",&n);        printf("%I64d\n",suan(n));    }}

0 0