数位DP 《 菜鸟与大牛在于一念之间》

来源:互联网 发布:韩国高考难度知乎 编辑:程序博客网 时间:2024/05/18 08:15

hdu3555 

#include<iostream>#include<algorithm>#include<cstdio>#include<string.h>using namespace std;__int64  dp[30][4];void init(){    memset(dp,0,sizeof(dp));    dp[0][0]=1;    for(int i=1; i<=20; i++)    {        dp[i][0]=dp[i-1][0]*10-dp[i-1][1];        //①:dp[i-1][0]*10代表当前可选择0-9十个数 ②:dp[i-1][1]当前以9开头的数的个数。        //③dp[i-1][0]*10-dp[i-1][1]代表不包含49的个数。        dp[i][1]=dp[i-1][0];        //①dp[i-1][0]代表以9开头的个数的数目        dp[i][2]=dp[i-1][2]*10+dp[i-1][1];        //以49开头的个数(分为两种情况:①dp[i][2]:x49xxx  ②当第一个x为4时满足条件dp[i][1]x9xxxx    }}int main(){    int T,len,flag,num[50];    __int64 t,ans;    init();    scanf("%d",&T);    while(T--)    {        len=flag=ans=0;        scanf("%I64d",&t);        t++;        memset(num,0,sizeof(num));        while(t)        {            num[++len]=t%10;            t/=10;        }        int  g=0;        for(int i=len; i>0; i--)        {            ans+=num[i]*dp[i-1][2];//开头为x49的个数            if(flag)            {                ans+=dp[i-1][0]*num[i];//开头为49的个数            }            if(!flag&&num[i]>4)            {                ans+=dp[i-1][1];//开头为x9(x>4)的个数            }            if(g==4&&num[i]==9)            {                flag=1;//判断。            }            g=num[i];        }        printf("%I64d\n",ans);    }    return 0;}



hdu2089 

数据比较弱:①可以暴搜②可以用数位DP:

#include<iostream>#include<algorithm>#include<cstdio>#include<string.h>using namespace std;int dp[1000010];bool f(int i){    while(i)    {        if(i%10==4||i%100==62)            return 1;        i/=10;    }    return 0;}int main(){    int n,m;    int ans,count;    memset(dp,0,sizeof(dp));    for(int i=1; i<1000000; i++)        if(f(i))            dp[i]=1;    while(scanf("%d%d",&n,&m))    {        ans=0;        if(n==0&&m==0)            break;        for(int i=n; i<=m; i++)            if(dp[i]==0)                ans++;        printf("%d\n",ans);    }    return 0;}



//该题分为三个状态://① 不含有不吉利的 ② 不含有 不吉利 但是以2开头的 ③ 含有不吉利的#include<iostream>#include<algorithm>#include<cstdio>#include<string.h>int dp[15][4];int nu[20];void init(){    memset(dp,0,sizeof(dp));    dp[0][0]=1;    for(int i=1; i<=9; i++)    {        //不含不吉利的数的个数:去掉①含有4的②含有62的        dp[i][0]=dp[i-1][0]*9-dp[i-1][1];        //不含有不吉利的数的个数:以2开头的数的个数        dp[i][1]=dp[i-1][0];        //含有不吉利的数的个数:①含有62的个数②以4开头的个数        dp[i][2]=dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0];    }}int ANS(int num){    memset(nu,0,sizeof(nu));    int len=0;    int ans=0;    int tem=num;    while(num)    {        nu[++len]=num%10;        num/=10;    }    int flag=0,last=0;    for(int i=len; i>0; i--)    {        ans+=dp[i-1][2]*nu[i];//不吉利的数        if(flag)        {            ans+=dp[i-1][0]*nu[i];//前面已经出现了不吉利的数        }        else        {            if(nu[i]>4)                ans+=dp[i-1][0];            if(nu[i]>6)                ans+=dp[i-1][1];            if(last==6&&nu[i]>2)                ans+=dp[i][1];        }        if(last==6&&nu[i]==2||nu[i]==4)            flag=1;        last=nu[i];    }    return tem-ans;}int main(){    int n,m;    init();    while(scanf("%d%d",&n,&m))    {        if(n==0&&m==0)            break;        printf("%d\n",ANS(m+1)-ANS(n));    }    return 0;}


原创粉丝点击